Gitlab CI正在我的docker-compose.yml文件中转义环境变量

时间:2020-10-02 11:55:38

标签: docker docker-compose gitlab-ci

我在公共GitLab CI服务器上为docker-compose.yml映像名称使用环境变量时遇到麻烦。我在docker中使用docker并安装了docker-compose的映像,但是当我尝试运行docker-compose命令时,由于某种原因,文件中的env var被转义了。即使我尝试在相同版本的docker / dicker-in-docker容器中运行,也不会在本地计算机上发生这种情况。

我的配置

# .gitlab-ci.yml
include:
  - template: 'Workflows/Branch-Pipelines.gitlab-ci.yml'

image: docker:19.03.13

services:
  - docker:19.03.13-dind

variables:
  # Use TLS https://docs.gitlab.com/ee/ci/docker/using_docker_build.html#tls-enabled
  DOCKER_HOST: tcp://docker:2376
  DOCKER_TLS_CERTDIR: "/certs"
  DOCKER_DRIVER: overlay

stages:
  - prep
  - build
  - test

before_script:
  - docker info
  - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
  - docker pull $CI_REGISTRY_IMAGE/ci-builder:latest || true
  - cp .env.ci .env

prep_build_container:
  stage: prep
  script:
    - docker pull $CI_REGISTRY_IMAGE/ci-builder:latest || true
    - docker build --cache-from $CI_REGISTRY_IMAGE/ci-builder:latest --tag $CI_REGISTRY_IMAGE/ci-builder:$CI_COMMIT_SHA --tag $CI_REGISTRY_IMAGE/ci-builder:latest ./docker/ci-builder
    - docker push $CI_REGISTRY_IMAGE/ci-builder:$CI_COMMIT_SHA
    - docker push $CI_REGISTRY_IMAGE/ci-builder:latest

build:
  stage: build
  image: $CI_REGISTRY_IMAGE/ci-builder:latest
  script:
    - env
    - less docker-compose.yml
    - docker-compose config
    - docker-compose pull
    - docker-compose build
include:
  - template: 'Workflows/Branch-Pipelines.gitlab-ci.yml'

image: docker:19.03.13

services:
  - docker:19.03.13-dind

variables:
  # Use TLS https://docs.gitlab.com/ee/ci/docker/using_docker_build.html#tls-enabled
  DOCKER_HOST: tcp://docker:2376
  DOCKER_TLS_CERTDIR: "/certs"
  DOCKER_DRIVER: overlay

stages:
  - prep
  - build
  - test

before_script:
  - docker info
  - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
  - docker pull $CI_REGISTRY_IMAGE/ci-builder:latest || true
  - cp .env.ci .env

prep_build_container:
  stage: prep
  script:
    - docker pull $CI_REGISTRY_IMAGE/ci-builder:latest || true
    - docker build --cache-from $CI_REGISTRY_IMAGE/ci-builder:latest --tag $CI_REGISTRY_IMAGE/ci-builder:$CI_COMMIT_SHA --tag $CI_REGISTRY_IMAGE/ci-builder:latest ./docker/ci-builder
    - docker push $CI_REGISTRY_IMAGE/ci-builder:$CI_COMMIT_SHA
    - docker push $CI_REGISTRY_IMAGE/ci-builder:latest

build:
  stage: build
  image: $CI_REGISTRY_IMAGE/ci-builder:latest
  script:
    - env
    - less docker-compose.yml
    - docker-compose config
    - docker-compose pull
    - docker-compose build
# docker-compose.yml
version: '3.4'

x-cache-from:
  - &api-cache-from
    cache_from:
      - "${CONTAINER_REGISTRY}/nginx:${CONTAINER_VERSION}"
      - "${CONTAINER_REGISTRY}/php:${CONTAINER_VERSION}"

services:
  php:
    build:
      context: ./api
      target: api_platform_php
      <<: *api-cache-from
    image: "${CONTAINER_REGISTRY}/php:${CONTAINER_VERSION}"
    healthcheck:
      interval: 10s
      timeout: 3s
      retries: 3
      start_period: 30s
    depends_on:
      - db
      - dev-tls
    volumes:
      - ./api:/srv/api:rw,cached
      - ./api/docker/php/conf.d/api-platform.dev.ini:/usr/local/etc/php/conf.d/api-platform.ini
      # if you develop on Linux, you may use a bind-mounted host directory instead
      # - ./api/var:/srv/api/var:rw
      - dev-certs:/certs:ro,nocopy
      # For dev purposes whilst working without access to private repos…
      - ../../coding-standards:/coding-standards

  api:
    build:
      context: ./api
      target: api_platform_nginx
      <<: *api-cache-from
    image: "${CONTAINER_REGISTRY}/nginx:${CONTAINER_VERSION}"
    depends_on:
      - php
    volumes:
      - ./api/public:/srv/api/public:ro

  vulcain:
    image: dunglas/vulcain
    environment:
      - CERT_FILE=/certs/localhost.crt
      - KEY_FILE=/certs/localhost.key
      - UPSTREAM=http://api
    depends_on:
      - api
      - dev-tls
    volumes:
      - dev-certs:/certs:ro,nocopy
    ports:
      - target: 443
        published: 8443
        protocol: tcp

  db:
    image: postgres:12-alpine
    environment:
      - POSTGRES_DB=api
      - POSTGRES_PASSWORD=!ChangeMe!
      - POSTGRES_USER=api-platform
    volumes:
      - db-data:/var/lib/postgresql/data:rw
      # you may use a bind-mounted host directory instead, so that it is harder to accidentally remove the volume and lose all your data!
      # - ./api/docker/db/data:/var/lib/postgresql/data:rw
    ports:
      - target: 5432
        published: 5432
        protocol: tcp

  mercure:
    image: dunglas/mercure
    environment:
      - ALLOW_ANONYMOUS=1
      - CERT_FILE=/certs/localhost.crt
      - CORS_ALLOWED_ORIGINS=*
      - DEMO=1
      - JWT_KEY=!ChangeMe!
      - KEY_FILE=/certs/localhost.key
      - PUBLISH_ALLOWED_ORIGINS=https://localhost:1337 # required for publishing from the demo page
    depends_on:
      - dev-tls
    volumes:
      - dev-certs:/certs:ro,nocopy
    ports:
      - target: 443
        published: 1337
        protocol: tcp

  client:
    build:
      context: ./client
      target: api_platform_client_development
      cache_from:
        - "${CONTAINER_REGISTRY}/client:${CONTAINER_VERSION}"
    image: "${CONTAINER_REGISTRY}/client:${CONTAINER_VERSION}"
    tty: true # https://github.com/facebook/create-react-app/issues/8688
    environment:
      - API_PLATFORM_CLIENT_GENERATOR_ENTRYPOINT=http://api
      - API_PLATFORM_CLIENT_GENERATOR_OUTPUT=src
    depends_on:
      - dev-tls
    volumes:
      - ./client:/usr/src/client:rw,cached
      - dev-certs:/usr/src/client/node_modules/webpack-dev-server/ssl:rw,nocopy
    ports:
      - target: 3000
        published: 443
        protocol: tcp

  admin:
    build:
      context: ./admin
      target: api_platform_admin_development
      cache_from:
        - "${CONTAINER_REGISTRY}/admin:${CONTAINER_VERSION}"
    image: "${CONTAINER_REGISTRY}/admin:${CONTAINER_VERSION}"
    tty: true # https://github.com/facebook/create-react-app/issues/8688
    depends_on:
      - dev-tls
    volumes:
      - ./admin:/usr/src/admin:rw,cached
      - dev-certs:/usr/src/admin/node_modules/webpack-dev-server/ssl:rw,nocopy
    ports:
      - target: 3000
        published: 444
        protocol: tcp

  dev-tls:
    build:
      context: ./docker/dev-tls
    volumes:
      - dev-certs:/certs:rw
    ports:
      - target: 80
        published: 80
        protocol: tcp

volumes:
  db-data: {}
  dev-certs: {}
# .env.ci
COMPOSE_PROJECT_NAME=myproject
CONTAINER_REGISTRY=${CI_REGISTRY_IMAGE}
CONTAINER_VERSION=${CI_COMMIT_SHORT_SHA}

构建输出

这是构建服务器上的输出。请注意$$步骤的输出上的双docker-compose config,在less docker-compose.yml输出中没有双…{p>

$ less docker-compose.yml
version: '3.4'
x-cache-from:
  - &api-cache-from
    cache_from:
      - "${CONTAINER_REGISTRY}/nginx"
      - "${CONTAINER_REGISTRY}/php:${CONTAINER_VERSION}"
services:
  php:
    build:
      context: ./api
      target: api_platform_php
      <<: *api-cache-from
    image: "${CONTAINER_REGISTRY}/php:${CONTAINER_VERSION}"
    healthcheck:
      interval: 10s
      timeout: 3s
      retries: 3
      start_period: 30s
    depends_on:
      - db
      - dev-tls
    volumes:
      - ./api:/srv/api:rw,cached
      - ./api/docker/php/conf.d/api-platform.dev.ini:/usr/local/etc/php/conf.d/api-platform.ini
      # if you develop on Linux, you may use a bind-mounted host directory instead
      # - ./api/var:/srv/api/var:rw
      - dev-certs:/certs:ro,nocopy
      # For dev purposes whilst working without access to private repos…
      - ../../coding-standards:/coding-standards
  api:
    build:
      context: ./api
      target: api_platform_nginx
      <<: *api-cache-from
    image: "${CONTAINER_REGISTRY}/nginx"
    depends_on:
      - php
    volumes:
      - ./api/public:/srv/api/public:ro
  vulcain:
    image: dunglas/vulcain
    environment:
      - CERT_FILE=/certs/localhost.crt
      - KEY_FILE=/certs/localhost.key
      - UPSTREAM=http://api
    depends_on:
      - api
      - dev-tls
    volumes:
      - dev-certs:/certs:ro,nocopy
    ports:
      - target: 443
        published: 8443
        protocol: tcp
  db:
    image: postgres:12-alpine
    environment:
      - POSTGRES_DB=api
      - POSTGRES_PASSWORD=!ChangeMe!
      - POSTGRES_USER=api-platform
    volumes:
      - db-data:/var/lib/postgresql/data:rw
      # you may use a bind-mounted host directory instead, so that it is harder to accidentally remove the volume and lose all your data!
      # - ./api/docker/db/data:/var/lib/postgresql/data:rw
    ports:
      - target: 5432
        published: 5432
        protocol: tcp
  mercure:
    image: dunglas/mercure
    environment:
      - ALLOW_ANONYMOUS=1
      - CERT_FILE=/certs/localhost.crt
      - CORS_ALLOWED_ORIGINS=*
      - DEMO=1
      - JWT_KEY=!ChangeMe!
      - KEY_FILE=/certs/localhost.key
      - PUBLISH_ALLOWED_ORIGINS=https://localhost:1337 # required for publishing from the demo page
    depends_on:
      - dev-tls
    volumes:
      - dev-certs:/certs:ro,nocopy
    ports:
      - target: 443
        published: 1337
        protocol: tcp
  client:
    build:
      context: ./client
      target: api_platform_client_development
      cache_from:
        - "${CONTAINER_REGISTRY}/client:${CONTAINER_VERSION}"
    image: "${CONTAINER_REGISTRY}/client:${CONTAINER_VERSION}"
    tty: true # https://github.com/facebook/create-react-app/issues/8688
    environment:
      - API_PLATFORM_CLIENT_GENERATOR_ENTRYPOINT=http://api
      - API_PLATFORM_CLIENT_GENERATOR_OUTPUT=src
    depends_on:
      - dev-tls
    volumes:
      - ./client:/usr/src/client:rw,cached
      - dev-certs:/usr/src/client/node_modules/webpack-dev-server/ssl:rw,nocopy
    ports:
      - target: 3000
        published: 443
        protocol: tcp
  admin:
    build:
      context: ./admin
      target: api_platform_admin_development
      cache_from:
        - "${CONTAINER_REGISTRY}/admin:${CONTAINER_VERSION}"
    image: "${CONTAINER_REGISTRY}/admin:${CONTAINER_VERSION}"
    tty: true # https://github.com/facebook/create-react-app/issues/8688
    depends_on:
      - dev-tls
    volumes:
      - ./admin:/usr/src/admin:rw,cached
      - dev-certs:/usr/src/admin/node_modules/webpack-dev-server/ssl:rw,nocopy
    ports:
      - target: 3000
        published: 444
        protocol: tcp
  dev-tls:
    build:
      context: ./docker/dev-tls
    volumes:
      - dev-certs:/certs:rw
    ports:
      - target: 80
        published: 80
        protocol: tcp
volumes:
  db-data: {}
  dev-certs: {}
$ docker-compose config
services:
  admin:
    build:
      cache_from:
      - $${CI_REGISTRY_IMAGE}/admin:$${CI_COMMIT_SHORT_SHA}
      context: /builds/good-technologies/crm/api/admin
      target: api_platform_admin_development
    depends_on:
    - dev-tls
    image: $${CI_REGISTRY_IMAGE}/admin:$${CI_COMMIT_SHORT_SHA}
    ports:
    - protocol: tcp
      published: 444
      target: 3000
    tty: true
    volumes:
    - /builds/good-technologies/crm/api/admin:/usr/src/admin:rw,cached
    - dev-certs:/usr/src/admin/node_modules/webpack-dev-server/ssl:rw,nocopy
  api:
    build:
      cache_from:
      - $${CI_REGISTRY_IMAGE}/nginx
      - $${CI_REGISTRY_IMAGE}/php:$${CI_COMMIT_SHORT_SHA}
      context: /builds/good-technologies/crm/api/api
      target: api_platform_nginx
    depends_on:
    - php
    image: $${CI_REGISTRY_IMAGE}/nginx
    volumes:
    - /builds/good-technologies/crm/api/api/public:/srv/api/public:ro
  client:
    build:
      cache_from:
      - $${CI_REGISTRY_IMAGE}/client:$${CI_COMMIT_SHORT_SHA}
      context: /builds/good-technologies/crm/api/client
      target: api_platform_client_development
    depends_on:
    - dev-tls
    environment:
      API_PLATFORM_CLIENT_GENERATOR_ENTRYPOINT: http://api
      API_PLATFORM_CLIENT_GENERATOR_OUTPUT: src
    image: $${CI_REGISTRY_IMAGE}/client:$${CI_COMMIT_SHORT_SHA}
    ports:
    - protocol: tcp
      published: 443
      target: 3000
    tty: true
    volumes:
    - /builds/good-technologies/crm/api/client:/usr/src/client:rw,cached
    - dev-certs:/usr/src/client/node_modules/webpack-dev-server/ssl:rw,nocopy
  db:
    environment:
      POSTGRES_DB: api
      POSTGRES_PASSWORD: '!ChangeMe!'
      POSTGRES_USER: api-platform
    image: postgres:12-alpine
    ports:
    - protocol: tcp
      published: 5432
      target: 5432
    volumes:
    - db-data:/var/lib/postgresql/data:rw
  dev-tls:
    build:
      context: /builds/good-technologies/crm/api/docker/dev-tls
    ports:
    - protocol: tcp
      published: 80
      target: 80
    volumes:
    - dev-certs:/certs:rw
  mercure:
    depends_on:
    - dev-tls
    environment:
      ALLOW_ANONYMOUS: '1'
      CERT_FILE: /certs/localhost.crt
      CORS_ALLOWED_ORIGINS: '*'
      DEMO: '1'
      JWT_KEY: '!ChangeMe!'
      KEY_FILE: /certs/localhost.key
      PUBLISH_ALLOWED_ORIGINS: https://localhost:1337
    image: dunglas/mercure
    ports:
    - protocol: tcp
      published: 1337
      target: 443
    volumes:
    - dev-certs:/certs:ro,nocopy
  php:
    build:
      cache_from:
      - $${CI_REGISTRY_IMAGE}/nginx
      - $${CI_REGISTRY_IMAGE}/php:$${CI_COMMIT_SHORT_SHA}
      context: /builds/good-technologies/crm/api/api
      target: api_platform_php
    depends_on:
    - db
    - dev-tls
    healthcheck:
      interval: 10s
      retries: 3
      start_period: 30s
      timeout: 3s
    image: $${CI_REGISTRY_IMAGE}/php:$${CI_COMMIT_SHORT_SHA}
    volumes:
    - /builds/good-technologies/crm/api/api:/srv/api:rw,cached
    - /builds/good-technologies/crm/api/api/docker/php/conf.d/api-platform.dev.ini:/usr/local/etc/php/conf.d/api-platform.ini:rw
    - dev-certs:/certs:ro,nocopy
    - /builds/good-technologies/coding-standards:/coding-standards:rw
  vulcain:
    depends_on:
    - api
    - dev-tls
    environment:
      CERT_FILE: /certs/localhost.crt
      KEY_FILE: /certs/localhost.key
      UPSTREAM: http://api
    image: dunglas/vulcain
    ports:
    - protocol: tcp
      published: 8443
      target: 443
    volumes:
    - dev-certs:/certs:ro,nocopy
version: '3.4'
volumes:
  db-data: {}
  dev-certs: {}
$ docker-compose pull
Pulling db      ... 
Pulling dev-tls ... 
Pulling admin   ... 
Pulling client  ... 
Pulling mercure ... 
Pulling php     ... 
Pulling api     ... 
Pulling vulcain ... 
ERROR: for client  invalid reference format: repository name must be lowercase
ERROR: for api  invalid reference format: repository name must be lowercase
ERROR: for admin  invalid reference format: repository name must be lowercase
ERROR: for php  invalid reference format: repository name must be lowercase
invalid reference format: repository name must be lowercase
invalid reference format: repository name must be lowercase
invalid reference format: repository name must be lowercase
invalid reference format: repository name must be lowercase

目前,我将对值进行硬编码,以便继续学习,但我真的很想理解,如果有人有什么聪明的主意,为什么这不起作用?

1 个答案:

答案 0 :(得分:0)

docker-compose存在问题。该问题已得到修复(在1.25.4和1.27.4之间),这就是为什么您可以在本地和GitLab上观察到不同的行为的原因。

如果您可以将worker上的docker-compose升级到最新版本,它应该可以解决此问题。否则,您可以尝试将cp .env.ci .env中的before_script替换为:

eval "echo \"$(cat .env.ci)\"" >> .env

该命令在写入.env.ci文件之前在.env内插环境变量。