Search code examples
dockerdocker-composegitlabcontainersgitlab-ci

How to run multiples docker container when run docker-compose up ( gitlab-ci)


I need to deploy a new container each time that i do "docker-compose up" because the container will run a SQL SERVER database in a Gitlab pipeline for each merge request that will be created in the repository.

Is there a flag that should be passed to do this? I know the --force-recreate, but it recreate the SAME container. I neeed to every time to the command docker-compose up been called to create another container with the same configurations.

There is the --scale SERVICE=NUM, but it is not what i need. Why? because when i scale i can not control which host port docker will grab and use.

how do i intend to do this? By a environment variable. Look:

docker-compose file

version: '2'

services:
  db:
    image: mcr.microsoft.com/mssql/server:2019-latest
    container_name: ${CI_PIPELINE_ID}
    environment:
      - ACCEPT_EULA=Y
      - SA_PASSWORD=${DATABASE_PASSWORD}
    ports:
      - "${CI_PIPELINE_ID}:1433"

my gitlab-ci:

stages:
  - database_deploy
  - build_and_test
  - database_stop

database_deploy:
  image: docker:latest
  stage: database_deploy
  services:
    - name: docker
  script:
    - apk add py-pip
    - pip install docker-compose==1.8.0
    - cd ./docker; docker-compose up -d; docker ps

build_and_test:
  image: maven:latest
  stage: build_and_test
  script:
    - mvn test -Dquarkus.test.profile=homolog
    - mvn checkstyle:check
  artifacts:
    paths:
      - target

database_stop: &database_stop
  image: docker:latest
  stage: database_stop
  services:
    - name: docker
  script:
    - docker stop $CI_PIPELINE_ID
    - docker rm -f $CI_PIPELINE_ID
    - docker ps


cleanup_deployment_failure:
  needs: ["build_and_test"]
  when: on_failure
  <<: *database_stop

Solution

  • Docker-compose groups your services in "projects". By default, the project name is the name of the directory that contains your docker-compose.yml file. When you run docker up, docker-compose will create any containers in the project that don't already exist.

    Since you want docker-compose up to create new containers every time -- with different configurations -- you need to tell docker-compose that it's running in a different project each time. You can do this with the --project-name (-p) flag.

    For example, let's say I have this docker-compose.yml:

    version: "3"
    
    services:
      web:
        image: "alpinelinux/darkhttpd"
        ports:
          - "${HOSTPORT}:8080"
    

    I can bring up multiple instances of this stack by setting HOSTPORT and specifying a project name for each invocation of docker-compsoe:

    $ HOSTPORT=8081 docker-compose -p project1 up -d
    $ HOSTPORT=8082 docker-compose -p project2 up -d
    

    After running those two commands, we see:

    CONTAINER ID   IMAGE                   COMMAND                  CREATED         STATUS         PORTS                                       NAMES
    825ea98cca55   alpinelinux/darkhttpd   "darkhttpd /var/www/…"   4 seconds ago   Up 3 seconds   0.0.0.0:8082->8080/tcp, :::8082->8080/tcp   project2_web_1
    776c12d38bbb   alpinelinux/darkhttpd   "darkhttpd /var/www/…"   9 seconds ago   Up 8 seconds   0.0.0.0:8081->8080/tcp, :::8081->8080/tcp   project1_web_1
    

    And I think that's exactly what you're looking for.

    Note that with this configuration, you will need to specify the project name and a value for HOSTPORT every time you run docker-compose.


    You can also set the project name using the COMPOSE_PROJECT_NAME environment variable. This means you can actually organize things using environment files.

    We can reproduce the above behavior by creating project1.env with:

    COMPOSE_PROJECT_NAME=project1
    HOSTPORT=8081
    

    And project2.env with:

    COMPOSE_PROJECT_NAME=project2
    HOSTPORT=8082
    

    And then running:

    $ docker-compose --env-file project1.env up -d
    $ docker-compose --env-file project2.env up -d
    

    As before, you'll need to provide --env-file every time you run docker-compose.