5
votes

I recently got into CI/CD, and a good starting point for me was GitLab, since they provide an easy interface for that and i got started about what pipelines and stages are, but i have run into some kind of contradictory thought about GitLab CI running on Docker.

My app runs on Docker Compose. It contains (blah blah) that makes it easy to build & run containers. Each service in the Docker Compose creates a single Docker container, excepting the php-fpm one, which is able to do the thing called "horizontal scale", so I can scale it later.

I will use that Docker Compose for production, I am currently using it in development and I want to use it too in CI/CD pipelines.

However the .gitlab-ci.yml provides support for only one image, so I have to build it and push it to either their GitLab Registry or Docker Hub in order to pull it later in the CI/CD process.

How can I build my Docker Compose's service as a single image in order to push it to the Registry/Docker so I can pull it in the CI/CD?

My project contains a docker folder and a docker-compose.yml. In the docker folder, each service has its own separate directory (php-fpm, nginx, mysql, etc.) and each one (prepare yourself) contains a Dockerfile with build details, especially the php-fpm one (deps and libs are strong with this one)

Each service in the docker-compose.yml has a build context in each of their own folder.

If I was unclear, I can provide additonal info.

3
This is a pretty common setup, nothing unusual.emix

3 Answers

1
votes

However the .gitlab-ci.yml provides support for only one image

This is not true. From the official documentation:

Your image will be named after the following scheme:

<registry URL>/<namespace>/<project>/<image>

GitLab supports up to three levels of image repository names. Following examples of image tags are valid:

registry.example.com/group/project:some-tag
registry.example.com/group/project/image:latest
registry.example.com/group/project/my/image:rc1

So the solution to your problem is simple - just build individual images and push them to GitLab container registry under different image name. The following config should give you an idea:

.template: &build_template
  image: docker:stable
  services:
    - docker:dind
  before_script:
    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
  script:
    - docker pull $CI_REGISTRY_IMAGE/$IMAGE_NAME:latest || true
    - if [ -z ${CI_COMMIT_TAG+x} ];
      then docker build
        --cache-from $CI_REGISTRY_IMAGE/$IMAGE_NAME:latest
        --file $DOCKERFILE_NAME
        --tag $CI_REGISTRY_IMAGE/$IMAGE_NAME:$CI_COMMIT_SHA
        --tag $CI_REGISTRY_IMAGE/$IMAGE_NAME:$CI_COMMIT_TAG
        --tag $CI_REGISTRY_IMAGE/$IMAGE_NAME:latest . ;
      else docker build
        --cache-from $CI_REGISTRY_IMAGE/$IMAGE_NAME:latest
        --file $DOCKERFILE_NAME
        --tag $CI_REGISTRY_IMAGE/$IMAGE_NAME:$CI_COMMIT_SHA
        --tag $CI_REGISTRY_IMAGE/$IMAGE_NAME:latest . ;
      fi
    - docker push $CI_REGISTRY_IMAGE/$IMAGE_NAME:$CI_COMMIT_SHA
    - if [ -z ${CI_COMMIT_TAG+x} ]; then
        docker push $CI_REGISTRY_IMAGE/$IMAGE_NAME:$CI_COMMIT_TAG;
      fi
    - docker push $CI_REGISTRY_IMAGE/$IMAGE_NAME:latest

build:image1:
  <<: *build_template
  variables:
    IMAGE_NAME: image1
    DOCKERFILE_NAME: Dockerfile.1

build:image2:
  <<: *build_template
  variables:
    IMAGE_NAME: image2
    DOCKERFILE_NAME: Dockerfile.2

And you should be able to pull the same image using $CI_REGISTRY_IMAGE/$IMAGE_NAME:$CI_COMMIT_SHA in later pipeline jobs or your compose file (provided that the variables are passed to where you run your compose file).

0
votes

I think you search something like this

# .gitlab-ci.yml

image: docker

services:
  - docker:dind

build:
  script:
    - apk add --no-cache py-pip
    - pip install docker-compose
    - docker-compose up -d

Also good to know:

0
votes

You don't need dind to run a docker-compose stack. You can run multiple docker-compose up commands.

acceptance_testing:
  stage: test
  before_script:
    - docker-compose -p $CI_JOB_ID up -d
  script:
    - docker-compose -p $CI_JOB_ID exec -T /run/your/test/suite.sh
  after_script:
    - docker-compose -p $CI_JOB_ID down -v --remove-orphans || true