Reputation: 2035
I have a .gitlab-ci.yml
file which contains following:
image: docker:latest
services:
- docker:dind
before_script:
- docker info
- docker-compose --version
buildJob:
stage: build
tags:
- docker
script:
- docker-compose build
But in ci-log
I receive message:
$ docker-compose --version
/bin/sh: eval: line 46: docker-compose: not found
What am I doing wrong?
Upvotes: 113
Views: 163105
Reputation: 670
Updated 2024
- After trying any option, currently it works properly (Tested)
variables:
DOCKER_HOST: tcp://docker:2375/
DOCKER_DRIVER: overlay2
DOCKER_TLS_CERTDIR: ""
stages:
- build
before_script:
- docker version
- docker-compose version
build_image:
image: docker:20-dind
stage: build
services:
- name: docker:20-dind
alias: docker
command: ["--tls=false"]
script:
# It takes your registry as pipe and protect user and password by default
- echo $CI_REGISTRY_PASSWORD | docker login -u $CI_REGISTRY_USER --password-stdin $CI_REGISTRY
- docker-compose up -d --build
- docker push $CI_REGISTRY/group/project/image:version
- echo "Image built successfully"
- docker images
NOTE: Replace your current /group/project/image:version
path checking gitlab repository in repository > packages and registries > container registry section, and also add variables if you need globally in project > settings > variables or in variables inside your .gitlab-ci.yml
instead.
Upvotes: 2
Reputation: 985
Deprecated
I created a simple docker container which has docker-compose
installed on top of docker:latest
. See https://hub.docker.com/r/tmaier/docker-compose/ or https://github.com/tmaier/docker-compose
Your .gitlab-ci.yml
file would look like this:
image: tmaier/docker-compose:latest
services:
- docker:dind
before_script:
- docker info
- docker-compose --version
buildJob:
stage: build
tags:
- docker
script:
- docker-compose build
Upvotes: 32
Reputation: 1524
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.sh
as entrypoint you'll need to override it back to/bin/sh -c
in your.gitlab-ci.yml
. Otherwise your pipeline will fail withNo such command: sh
image:
name: docker/compose:latest
entrypoint: ["/bin/sh", "-c"]
Upvotes: 120
Reputation: 3874
As a consequence of https://github.com/docker-library/docker/pull/361 just do
# docker-compose.yml
version: '2'
services:
hello:
image: hello-world
# .gitlab-ci.yml
myjob:
image: docker:latest
services:
- docker:dind
script:
- docker --version
- docker compose version
If you are not using the official docker "docker" image, do not install compose with a package manager as most distributions are outdated. Official install instructions point to either use the downloads.docker.com repository in its diverse forms for each Linux distribution or to simply download the github release artifact, which I think is leaner for a CI usage:
myjob:
- mkdir -p ~/.docker/cli-plugins
- (wget --no-verbose --no-clobber https://github.com/docker/compose/releases/latest/download/docker-compose-linux-x86_64 --output-document ~/.docker/cli-plugins/docker-compose || true) # ideally you would cache this binary
- chmod a+x ~/.docker/cli-plugins/docker-compose
- ln --symbolic ~/.docker/cli-plugins/docker-compose /usr/local/bin/docker-compose
script:
- docker-compose version
Upvotes: 1
Reputation: 6487
Deprecated
docker-compose
can be installed as a Python package, which is not shipped with your image. The image you chose does not even provide an installation of Python:
$ docker run --rm -it docker sh
/ # find / -iname "python"
/ #
Looking for Python gives an empty result. So you have to choose a different image, which fits to your needs and ideally has docker-compose installed or you maually create one.
The docker image you chose uses Alpine Linux. You can use it as a base for your own image or try a different one first if you are not familiar with Alpine Linux.
I had the same issue and created a Dockerfile in a public GitHub repository and connected it with my Docker Hub account and chose an automated build to build my image on each push to the GitHub repository. Then you can easily access your own images with the GitLab CI.
Upvotes: 16
Reputation: 2121
there is tiangolo/docker-with-compose
which works:
image: tiangolo/docker-with-compose
stages:
- build
- test
- release
- clean
before_script:
- docker login -u gitlab-ci-token -p $CI_BUILD_TOKEN registry.gitlab.com
build:
stage: build
script:
- docker-compose -f docker-compose-ci.yml build --pull
test1:
stage: test
script:
- docker-compose -f docker-compose-ci.yml up -d
- docker-compose -f docker-compose-ci.yml exec -T php ...
Upvotes: 5
Reputation: 6487
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.
Upvotes: 99
Reputation: 4667
It really took me some time to get it working with Gitlab.com shared runners.
I'd like to say "use docker/compose:latest
and that's it", but unfortunately I was not able to make it working, I was getting Cannot connect to the Docker daemon at tcp://docker:2375/. Is the docker daemon running?
error even when all the env variables were set.
Neither I like an option to install five thousands of dependencies to install docker-compose
via pip.
Fortunately, for the recent Alpine versions (3.10+) there is docker-compose package in Alpine repository. It means that @n2o's answer can be simplified to:
test:
image: docker:19.03.0
variables:
DOCKER_DRIVER: overlay2
# Create the certificates inside this directory for both the server
# and client. The certificates used by the client will be created in
# /certs/client so we only need to share this directory with the
# volume mount in `config.toml`.
DOCKER_TLS_CERTDIR: "/certs"
services:
- docker:19.03.0-dind
before_script:
- apk --no-cache add docker-compose # <---------- Mind this line
- docker info
- docker-compose --version
stage: test
script:
- docker-compose build
This worked perfectly from the first try for me. Maybe the reason other answers didn't was in some configuration of Gitlab.com shared runners, I don't know...
Upvotes: 2
Reputation: 3406
I think most of the above are helpful, however i needed to collectively apply them to solve this problem, below is the script which worked for me
I hope it works for you too
Also note, in your docker compose this is the format you have to provide for the image name
<registry base url>/<username>/<repo name>/<image name>:<tag>
image:
name: docker/compose:latest
entrypoint: ["/bin/sh", "-c"]
variables:
DOCKER_HOST: tcp://docker:2375/
DOCKER_DRIVER: overlay2
services:
- docker:dind
stages:
- build_images
before_script:
- docker version
- docker-compose version
- docker login -u $CI_REGISTRY_USER -p $CI_JOB_TOKEN $CI_REGISTRY
build:
stage: build_images
script:
- docker-compose down
- docker-compose build
- docker-compose push
Upvotes: 3
Reputation: 1003
Alpine linux now has a docker-compose package in their "edge" branch, so you can install it this way in .gitlab-ci.yml
a-job-with-docker-compose:
image: docker
services:
- docker:dind
script:
- apk add docker-compose --update-cache --repository http://dl-3.alpinelinux.org/alpine/edge/testing/ --allow-untrusted
- docker-compose -v
Upvotes: -1
Reputation: 109
If you don't want to provide a custom docker image with docker-compose preinstalled, you can get it working by installing Python during build time. With Python installed you can finally install docker-compose ready for spinning up your containers.
image: docker:latest
services:
- docker:dind
before_script:
- apk add --update python py-pip python-dev && pip install docker-compose # install docker-compose
- docker version
- docker-compose version
test:
cache:
paths:
- vendor/
script:
- docker-compose up -d
- docker-compose exec -T php-fpm composer install --prefer-dist
- docker-compose exec -T php-fpm vendor/bin/phpunit --coverage-text --colors=never --whitelist src/ tests/
Use docker-compose exec with -T if you receive this or a similar error:
$ docker-compose exec php-fpm composer install --prefer-dist
Traceback (most recent call last):
File "/usr/bin/docker-compose", line 9, in <module>
load_entry_point('docker-compose==1.8.1', 'console_scripts', 'docker-compose')()
File "/usr/lib/python2.7/site-packages/compose/cli/main.py", line 62, in main
command()
File "/usr/lib/python2.7/site-packages/compose/cli/main.py", line 114, in perform_command
handler(command, command_options)
File "/usr/lib/python2.7/site-packages/compose/cli/main.py", line 442, in exec_command
pty.start()
File "/usr/lib/python2.7/site-packages/dockerpty/pty.py", line 338, in start
io.set_blocking(pump, flag)
File "/usr/lib/python2.7/site-packages/dockerpty/io.py", line 32, in set_blocking
old_flag = fcntl.fcntl(fd, fcntl.F_GETFL)
ValueError: file descriptor cannot be a negative integer (-1)
ERROR: Build failed: exit code 1
Upvotes: 10