dockerdocker-composegitlabgitlab-cigitlab-pipelines

Build and push docker-compose image into container registry


I would to create a docker image using docker-compose and push it into the gitlab container registry. The docker-compose file has some build.args so during compile compile I pass the env file using the --env-file flag. The Dockerfile image is a two step: base and production and this is the contents:

FROM node:17.0-alpine AS base

ARG GITLAB_ACCESS_TOKEN

WORKDIR /usr/src/app

COPY .npmrc ./
COPY package*.json ./

RUN npm i

COPY . .

FROM base AS production

RUN npm run build

This is the docker-compose.yml:

version: '3.8'
services: 
  aaa-bbb:
    container_name: ccc
    environment:
      - GITLAB_ACCESS_TOKEN=${GITLAB_ACCESS_TOKEN}
    build:
      context: .
      dockerfile: Dockerfile
      target: base
      args:
        GITLAB_ACCESS_TOKEN: ${GITLAB_ACCESS_TOKEN}
        PORT: ${PORT}
    image: aaa-bbb/ccc:${TAG_VERSION}
    restart: always
    ports:
      - 80:${PORT}
    command: yarn start:dev

and this one is the docker-compose.prod.yml:

version: '3.8'
services: 
  aaa-bbb:
    container_name: ccc
    environment:
      - GITLAB_ACCESS_TOKEN=${GITLAB_ACCESS_TOKEN}
    build:
      context: .
      dockerfile: Dockerfile
      target: production
      args:
        GITLAB_ACCESS_TOKEN: ${GITLAB_ACCESS_TOKEN}
        PORT: ${PORT}
    image: aaa-bbb/ccc:${TAG_VERSION}
    restart: always
    ports:
      - 80:${PORT}
    command: yarn start:prd

To build the image I use this command: docker-compose --env-file ./config/.production.env -f docker-compose.yml -f docker-compose.prod.yml build --no-cache

This is the gitlab pipeline step to build and store into the container regristry the docker image:

create_image:
  image: docker
  stage: create-image
  services:
    - docker:dind
  before_script:
    - TAG_VERSION=$(awk -F= '$1 == "TAG_VERSION" { print $2 }' ./config/.production.env)
    - apk add --no-cache docker-compose
    - docker image prune -f
    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
  script:
    - echo "🛠 Image creation started..."
    - docker-compose --env-file ./config/.production.env -f docker-compose.yml -f docker-compose.prod.yml build --no-cache
    - docker-compose --env-file ./config/.production.env push aaa-bbb/ccc:${TAG_VERSION}
    - echo "📦 Image created successfully!"

This is the output of the pipeline:

Removing intermediate container 1187fec9a21e
 ---> b0c14918a07b
[Warning] One or more build-args [PORT] were not consumed
Successfully built b0c14918a07b
Successfully tagged aaa-bbb/ccc:1.0.0
$ docker-compose --env-file ./config/.production.env push aaa-bbb/ccc:${TAG_VERSION}
No such service: aaa-bbb/ccc:1.0.0
Cleaning up project directory and file based variables 00:00
ERROR: Job failed: exit code 1

As you can see, there is this warning: [Warning] One or more build-args [PORT] were not consumed that during my test in local it doesn't appear and second I have a service tagged as aaa-bbb/ccc:1.0.0 but I can't push it because there isn't the service.

How can I fix this problems?


Solution

  • your first issue is that in your docker-compose.yml you defined a build arg named PORT, but that is not present in your Dockerfile. Hence docker warns about it being defined but not used.

    You can fix that by adding

    ARG PORT
    EXPOSE ${PORT}
    

    to the end of the Dockerfile. If you want to set a default value (for example HTTP port 80) for as the port you can use this form: ARG PORT=80.

    If you need any more information about Dockerfiles, you can read more about it in its reference documentation at https://docs.docker.com/engine/reference/builder/

    But that does not lead to the error. When pushing with docker-compose you use the service name instead of the image. So in your case the correct command would be

    docker-compose --env-file ./config/.production.env push aaa-bbb
    

    Also, you need to add the full URL for the image name in docker-compose.yml. I.e.:

    services: 
      aaa-bbb:
        [redacted]
        image: your.gitlab.instance/perhapssomegroup/aaa-bbb/ccc:${TAG_VERSION}
        [redacted]
    

    You can read more about docker-compose at https://docs.docker.com/compose/reference/ and about its yml file at https://docs.docker.com/compose/compose-file/compose-file-v3/

    I suggest to have all the documentation links I posted on speed-dial (also called bookmark) as you might need them a lot.