EDIT (2023): Do not keep using docker-compose! Please migrate to docker compose, which is now part of the docker image and a 99% drop-in replacement of docker-compose. Ironically, if you (now) use docker:latest, the question does not apply. See Docker's documentation on Compose V2. The answer below only applies to docker-compose, AKA Compose V1, which is to be discontinued/become unsupported.
Docker also provides an official docker-compose image: docker/compose
This is the ideal solution if you don't want to install it every pipeline.
Note that in the latest version of GitLab CI/Docker you will likely need to give privileged access to your GitLab CI Runner and configure/disable TLS. See Use docker-in-docker workflow with Docker executor
variables:
DOCKER_HOST: tcp://docker:2375/
DOCKER_DRIVER: overlay2
# Official docker compose image.
image:
name: docker/compose:latest
services:
- docker:dind
before_script:
- docker version
- docker-compose version
build:
stage: build
script:
- docker-compose down
- docker-compose build
- docker-compose up tester-image
Note that in versions of docker-compose earlier than 1.25:
Since the image uses
docker-compose-entrypoint.shas entrypoint you'll need to override it back to/bin/sh -cin your.gitlab-ci.yml. Otherwise your pipeline will fail withNo such command: sh
image:
name: docker/compose:latest
entrypoint: ["/bin/sh", "-c"]
Answer from webmaster777 on Stack OverflowEDIT (2023): Do not keep using docker-compose! Please migrate to docker compose, which is now part of the docker image and a 99% drop-in replacement of docker-compose. Ironically, if you (now) use docker:latest, the question does not apply. See Docker's documentation on Compose V2. The answer below only applies to docker-compose, AKA Compose V1, which is to be discontinued/become unsupported.
Docker also provides an official docker-compose image: docker/compose
This is the ideal solution if you don't want to install it every pipeline.
Note that in the latest version of GitLab CI/Docker you will likely need to give privileged access to your GitLab CI Runner and configure/disable TLS. See Use docker-in-docker workflow with Docker executor
variables:
DOCKER_HOST: tcp://docker:2375/
DOCKER_DRIVER: overlay2
# Official docker compose image.
image:
name: docker/compose:latest
services:
- docker:dind
before_script:
- docker version
- docker-compose version
build:
stage: build
script:
- docker-compose down
- docker-compose build
- docker-compose up tester-image
Note that in versions of docker-compose earlier than 1.25:
Since the image uses
docker-compose-entrypoint.shas entrypoint you'll need to override it back to/bin/sh -cin your.gitlab-ci.yml. Otherwise your pipeline will fail withNo such command: sh
image:
name: docker/compose:latest
entrypoint: ["/bin/sh", "-c"]
Following the official documentation:
# .gitlab-ci.yml
image: docker
services:
- docker:dind
build:
script:
- apk add --no-cache docker-compose
- docker-compose up -d
Sample docker-compose.yml:
version: "3.7"
services:
foo:
image: alpine
command: sleep 3
bar:
image: alpine
command: sleep 3
We personally do not follow this flow anymore, because you loose control about the running containers and they might end up running endless. This is because of the docker-in-docker executor. We developed a python-script as a workaround to kill all old containers in our CI, which can be found here. But I do not suggest to start containers like this anymore.
How to use Docker Compose In Gitlab CI
Using docker-compose in a GitLab CI pipeline - Stack Overflow
Gitlab inside docker
How to install GitLab using Docker Compose?
Videos
The problem
This is complex problem.
The docker:latest image is based on alpine (Alpine Linux), which is built using musl-libc. This system is very barebones, and as such doesn't have everything a full-fledged desktop Linux might have. In fact, dynamic executables need to be compiled specifically for this system.
docker-compose is a Python application, bundled into a Linux executable using PyInstaller. These executables are really only expected to be able to run on the system which they were built. If you run an alpine container, and apk add file, you can see that the (dynamically-linked) executable you downloaded is expecting a specific interpreter.
# file /usr/local/bin/docker-compose
/usr/local/bin/docker-compose.pyinstaller: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=00747fe5bcde089bb4c2f1ba7ab5348bc02ac5bf, stripped
The problem is /lib64/ld-linux-x86-64.so.2 doesn't exist in alpine. In fact, /lib64 doesn't even exist.
The solution
Because docker-compose is a Python application, it can also be installed using pip:
Testing this inside an alpine container:
$ docker run --rm -it alpine /bin/bash
Here are the commands you can run manually, or add to your .gitlab-ci.yml before_script:
# apk add --no-cache python py2-pip
...
# pip install --no-cache-dir docker-compose
...
# docker-compose -v
docker-compose version 1.11.1, build 7c5d5e4
It turns out there is actually an open issue for this:
- https://github.com/docker/compose/issues/3465
Docker-compose is now an official image. You can put
image:
name: docker/compose:1.23.2
entrypoint: [""]
at the top of your .gitlab-ci.yml. You need to remove the default entrypoint of the compose image, which is done by the second line. After that, you can use both docker and docker-compose.
This works per GitLab 9.4. You can also build a custom image
FROM docker/compose:1.23.2
ENTRYPOINT []
and use it as your image.