Передайте --build-arg или используйте переменные окружения в двухэтапном Dockerfile в Gitlab - PullRequest
2 голосов
/ 19 апреля 2019

Мой минимальный макет тестового проекта выглядит следующим образом.

├── deployment
│   ├── build.sh
│   └── nginx
│       └── nginx.conf
├── Dockerfile
├── next.config.js
├── package.json
├── package-lock.json
└── pages
    ├── _app.js
    └── index.js

Содержимое Dockerfile:

FROM node as build-stage

ARG K8S_SECRET_PUB
ENV K8S_SECRET_PUB ${K8S_SECRET_PUB}

ARG SRV
ENV SRV ${SRV}

WORKDIR /app
COPY package*json /app/
RUN npm install --production
COPY ./ /app/
RUN npm run export


FROM nginx:1.15-alpine

RUN rm /etc/nginx/nginx.conf
COPY --from=build-stage /app/out /www
COPY deployment/nginx/nginx.conf /etc/nginx/
EXPOSE 5000

Цель состоит в том, чтобы переменные среды K8S_SECRET_PUB и SRV были переданы процессу сборки. npm run export выполняет next build && next export для получения статических файлов, которые должен обслуживать сервер nginx.

Содержимое next.config.js:

require('dotenv').config();

module.exports = {
  serverRuntimeConfig: {
    srv: process.env.SRV
  },
  publicRuntimeConfig: {
    pub: process.env.K8S_SECRET_PUB
  }
};

Содержание страниц / _app.js:

import App from 'next/app';
import getConfig from 'next/config';

const { serverRuntimeConfig, publicRuntimeConfig } = getConfig();

class MyApp extends App {
  render() {
    return (
      <div>
        <h1>
          {serverRuntimeConfig.srv || 'SRV not accessible from client :p'}
        </h1>
        <h1>{publicRuntimeConfig.pub || 'PUB not set'}</h1>
      </div>
    );
  }
}

export default MyApp;

При локальном построении образа докера с помощью docker build --build-arg K8S_SECRET_PUB=puppy --build-arg SRV=serverval -t my_image . я могу запустить контейнер с помощью docker run -p 5000:5000 my_image.

Доступ к работающему контейнеру дает ожидаемый результат. Проверка файловой системы дополнительно показывает, что переданные сквозные аргументы сборки собраны и файлы были записаны соответствующим образом.

testing the docker image locally

Однако, когда я отправляю этот код в Gitlab, развернутый nginx выглядит так:

running it on Gitlab

Я хотел бы, чтобы переменные окружения, которые я определил через пользовательский интерфейс Gitlab в меню «Настройки» -> «CI / CD», были выбраны и использованы на этапе сборки, определенном в Dockerfile. Поскольку в остальном мы были довольны Auto Dev, мы еще не создали и не проверили файл .gitlab-ci.yml.


Обновление № 1

Немного повозившись, теперь у меня есть доступ к переменным окружения, но я потерял удобство Auto DevOps.

Я добавил deployment/build.sh с этим содержанием:

#!/bin/sh
docker build --build-arg K8S_SECRET_PUB="${K8S_SECRET_PUB}" --build-arg SRV="${SRV}" -t my_image .

Я также начал с .gitlab-ci.yml, который содержит это:

stages:
    - build
    - review
    - deploy
    - clean

image: docker:latest

services:
    - docker:dind

build:
    stage: build
    script:
        - sh ./deployment/build.sh
        - mkdir image
        - docker save my_image > image/my_image.tar
    artifacts:
        paths:
            - image

После отправки хранилища в Gitlab конвейер завершается успешно, и я могу загрузить артефакт, разархивировать его, загрузить через docker load -i image/my_image.tar и запустить его. И, конечно же, страница загружается с определенными переменными из пользовательского интерфейса Gitlab CI / CD. Однако теперь я потерял все остальные этапы процесса развертывания (что является основной причиной, по которой я не хотел писать .gitlab-ci.yml, во-первых).


Обновление № 2

Работая с шаблоном Auto DevOps, который я нашел в https://gitlab.com/gitlab-org/gitlab-ce/blob/master/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml Я внес следующие изменения:

  • комментируя строку - template: Jobs/Build.gitlab-ci.yml
  • замените alpine на изображение докера
  • добавлено CODE_QUALITY_DISABLED: "true" в раздел переменных, потому что проверка качества кода заняла слишком много времени
  • добавить разделы служб и сборки из моей предыдущей попытки, описанной выше

Теперь я застрял на стадии обзора.

Application should be accessible at: http://*my_image_url*
Waiting for deployment "review-branchname-abcxyz" rollout to finish: 0 of 1 updated replicas are available...

1 Ответ

1 голос
/ 19 апреля 2019

После обновления №2 это изменения, которые я сделал, чтобы заставить его работать.

Переписал .gitlab-ci.yml:

image: docker:latest

variables:
  CI_APPLICATION_TAG: $CI_COMMIT_SHA
  CI_APPLICATION_REPOSITORY: $CI_REGISTRY_IMAGE/$CI_COMMIT_REF_SLUG
  CODE_QUALITY_DISABLED: "true"

  KUBERNETES_VERSION: 1.11.9
  HELM_VERSION: 2.13.1

  DOCKER_DRIVER: overlay2

  ROLLOUT_RESOURCE_TYPE: deployment

stages:
  - build
  - test
  - deploy # dummy stage to follow the template guidelines
  - review
  - dast
  - staging
  - canary
  - production
  - incremental rollout 10%
  - incremental rollout 25%
  - incremental rollout 50%
  - incremental rollout 100%
  - performance
  - cleanup

include:
#  - template: Jobs/Build.gitlab-ci.yml
  - template: Jobs/Test.gitlab-ci.yml
  - template: Jobs/Code-Quality.gitlab-ci.yml
  - template: Jobs/Deploy.gitlab-ci.yml
  - template: Jobs/Browser-Performance-Testing.gitlab-ci.yml
  - template: Security/DAST.gitlab-ci.yml
  - template: Security/Container-Scanning.gitlab-ci.yml
  - template: Security/Dependency-Scanning.gitlab-ci.yml
  - template: Security/License-Management.gitlab-ci.yml
  - template: Security/SAST.gitlab-ci.yml

# Override DAST job to exclude master branch
dast:
  except:
    refs:
      - master

services:
    - docker:dind

build:
    stage: build
    script:
        - sh ./deployment/build.sh

Использовал больше из шаблона, который я нашел, и переписал файл deploy / build.sh:

if ! docker info &>/dev/null; then
  if [ -z "$DOCKER_HOST" -a "$KUBERNETES_PORT" ]; then
    export DOCKER_HOST='tcp://localhost:2375'
  fi
fi

if [[ -n "$CI_REGISTRY_USER" ]]; then
  echo "Logging to GitLab Container Registry with CI credentials..."
  docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" "$CI_REGISTRY"
fi

if [[ -f Dockerfile ]]; then
  echo "Building Dockerfile-based application..."
else
  echo "Building Heroku-based application using gliderlabs/herokuish docker image..."
  cp /build/Dockerfile Dockerfile
fi

docker build --build-arg K8S_SECRET_PUB="${K8S_SECRET_PUB}" --build-arg SRV="${SRV}" --tag "$CI_APPLICATION_REPOSITORY:$CI_APPLICATION_TAG" .

docker push "$CI_APPLICATION_REPOSITORY:$CI_APPLICATION_TAG"
...