Code
Consider the following docker-compose.yml configuration:
version: "3.9"
services:
tests:
image: tests
tty: true
depends_on:
- "server"
links:
- "server:srv"
client:
image: client
tty: true
depends_on:
- "server"
links:
- "server:srv"
server:
image: server
tty: true
ports:
- "8081:80"
The client and tests containers run until finished. The server container runs indefinitely.
My Problem
I would like to run docker-compose till both the tests and client containers are done and set the exit status of docker-compose to 0 if (and only if) both ended up successfully. Upon failure, I expect any arbitrary error code to return.
What have I tried
docker-compose -f docker/docker-compose.yml up --exit-code-from tests
This runs till tests are finished, but does not wait for the client.
docker-compose -f docker/docker-compose.yml up --exit-code-from tests client
Does not work.
My Question
How can I run docker-compose and let it wait till a specific set of containers are finished, and set its success exit code iff all finished successfully?
Related
I have the following docker-compose.yml file which specifies that the backend service should wait until the postgres service is healthy before starting the backend service. Apparently, postgres service is already healthy even if it is still running its startup script.
This is my docker-compose.yml file.
version: "3.7"
services:
backend:
build: .
ports:
- "8080:8080"
env_file:
- .env
depends_on:
postgres:
condition: service_healthy
postgres:
image: postgres:13
ports:
- "${DB_PORT}:${DB_PORT}"
env_file:
- .env
volumes:
- ./initdb.d:/docker-entrypoint-initdb.d
- data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
interval: 5s
timeout: 10s
retries: 5
volumes:
data:
I am mounting a startup script that runs for quite a while in the ./initdb.d file. The startup script will populate the DB with 1M rows. It seems like when the startup scripts are running, the backend service can't connect to postgres. Right now, my best solution is simply to add restart: on-failure:5 to wait for the startup scripts to finish. Is there a more robust way to achieve this though?
I have a problem with the deployment of Gitlab-runner on my structure with Docker-compose.
I want to register my gitlab-runner automaticaly but when i start my compose, all is good, and after that, my container is destroy.
That's my compose :
`version: '3.6'
services:
gitlab-runner:
image: gitlab/gitlab-runner:latest
container_name: gitlab-runner
restart: 'no'
depends_on:
- gitlab
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- /myrepository/gitlab-runner:/etc/gitlab-runner
command :
- register
- --non-interactive
- --url=MY_GITLAB_URL
- --registration-token=MY_TOKEN
- --executor=docker
- --docker-image=ruby:2.7
- --name=myrunner
- --docker-pull-policy=always
- --locked=false
- --run-untagged=false
- --docker-privileged=false
- --limit=0
- --tag-list=general,test
networks:
- gitlab
`
If i launch my runner without the "command" bloc of my docker-compose, it's ok, it stay alive and i can docker exec "gitlab-runner register" without lost my container.
If i launch my docker-compose with "command" bloc, my container will be create a new runner (i can see the runner created on my gitlab) but the container of gitlab runner is instant destroy.
Do you have any explication about that and a solution?
Thanks
I guess that the container is destroyed as soon as the command ends, because it's the way containers work. You must have a process running inside the container if you want it to be alive.
Try something like this:
tty: true
command:
- /bin/sh
- -c
- |
register --non-interactive --url=MY_GITLAB_URL --registration-token=MY_TOKEN --executor=docker --docker-image=ruby:2.7 --name=myrunner --docker-pull-policy=always --locked=false --run-untagged=false --docker-privileged=false --limit=0 --tag-list=general,test &&
sleep infinity
More info:
Docker Compose keep container running
How chain sleep command in docker compose?
I have a schema script /data/cb-create.sh that I have made available on a container volume. When I run docker-compose up, my server is not initialized at the time command is executed. So those commands fail because the server isn't launched just yet. I do not see a Starting Couchbase Server -- Web UI available at http://<ip>:8091 log line when the .sh script is running to initialize the schema. This is my docker compose file. How can I sequence it properly?
version: '3'
services:
couchbase:
image: couchbase:community-6.0.0
deploy:
replicas: 1
ports:
- 8091:8091
- 8092:8092
- 8093:8093
- 8094:8094
- 11210:11210
volumes:
- ./:/data
command: /bin/bash -c "/data/cb-create.sh"
container_name: couchbase
volumes:
kafka-data:
First: You should choose either an entrypoint or a command statement.
I guess an option is to write a small bash script where you put these commands in order.
Then in the command you specify running that bash script.
So i currently can use "docker-compose up test" which only runs my database and my testing scripts. I want to be able to us say docker-compose up app" or something like that that runs everything besides testing. That way Im not running unnecessary containers. Im not sure if theres a way but thats what I was wondering. If possible Id appreciate some links to some that already do that and I can figure out the rest. Basically can I only run certain containers with a single command without running the others.
Yaml
version: '3'
services:
webapp:
build: ./literate-app
command: nodemon -e vue,js,css start.js
depends_on:
- postgres
links:
- postgres
environment:
- DB_HOST=postgres
ports:
- "3000:3000"
networks:
- literate-net
server:
build: ./readability-server
command: nodemon -L --inspect=0.0.0.0:5555 server.js
networks:
- literate-net
redis_db:
image: redis:alpine
networks:
- literate-net
postgres:
restart: 'always'
#image: 'bitnami/postgresql:latest'
volumes:
- /bitnami
ports:
- "5432:5432"
networks:
- literate-net
environment:
- "FILLA_DB_USER=my_user"
- "FILLA_DB_PASSWORD=password123"
- "FILLA_DB_DATABASE=my_database"
- "POSTGRES_PASSWORD=password123"
build: './database-creation'
test:
image: node:latest
build: ./test
working_dir: /literate-app/test
volumes:
- .:/literate-app
command:
npm run mocha
networks:
- literate-net
depends_on:
- postgres
environment:
- DB_HOST=postgres
networks:
literate-net:
driver: bridge
I can run docker-compose up test
Which only runs the postgres. Though I'd like to be able to just run my app without having to run my testing container.
Edit
Thanks to #ideam for the link
I was able to create an additional yaml file for just testing.
For those that dont want to look it up simply create a new yaml file like so
docker-compose.dev.yml
replace dev with whatever you like besides override which causes docker-compose up to automatically run that unless otherwise specified
To run the new file simply call
docker-compose -f docker-compose.dev.yml up
The -f is a flag for selecting a certain file to run. You can run multiple files to have different enviornments set-up
Appreciate the help
docker-compose up <service_name> will start only the service you have specified and its dependencies. (those specified in the dependends_on option.)
you may also define multiple services in the docker-compose up command:
docker-compose up <service_name> <service_name>
note - what does it mean "start the service and its dependecies"?
usually your production services (containers) are attached to each other via the dependes_on chain, therefore you can start only the last containers of the chain. for example, take the following compose file:
version: '3.7'
services:
frontend:
image: efrat19/vuejs
ports:
- "80:8080"
depends_on:
- backend
backend:
image: nginx:alpine
depends_on:
- fpm
fpm:
image: php:7.2
testing:
image: hze∂ƒxhbd
depends_on:
- frontend
all the services are chained in the depends_on option, while the testing container is down bellow the frontend. so when you hit docker-compose up frontend docker will run the fpm first, then the backend, then the frontend, and it will ignore the testing container, which is not required for running the frontend.
Starting with docker-compose 1.28.0 the new service profiles are just made for that! With profiles you can mark services to be only started in specific profiles:
services:
webapp:
# ...
server:
# ...
redis_db:
# ...
postgres:
# ...
test:
profiles: ["test"]
# ...
docker-compose up # start only your app services
docker-compose --profile test up # start app and test services
docker-compose run test # run test service
Maybe you want to share your docker-compose.yml for a better answer than this.
For reusing docker-compose configurations have a look at https://docs.docker.com/compose/extends/#example-use-case which explains the combination of multiple configuration files for reuse of configs for different use cases (test, production, etc.)
How do I get a service container to exit once the dependent container has finished?
I have test suite running in the app_unittestbot container that depends_on a postgresql db server (postgres:9.5-alpine) running in separate container. Once the test suite exits, I want to check the return code of the test suite and halt the database container. With the docker-compose.yml below, the db service container never halts.
docker-compose.yml
version: '2.1'
services:
app_postgresql95:
build: ./postgresql95/
ports:
- 54321:5432
app_unittestbot:
command: /root/wait-for-it.sh app_postgresql95:5432 --timeout=60 -- nose2 tests
build: ./unittestbot/
links:
- app_postgresql95
volumes:
- /app/src:/src
depends_on:
- 'app_postgresql95'
You can run docker-compose up --abort-on-container-exit to have compose stop all the containers if any one of them exits. That will likely solve your use case.
For something a little more resilient, I'd probably split this into two compose files so that an abort on postgresql doesn't get accidentally registered as a successful test. Then you'd just run those files in the order you need:
docker-compose -f docker-compose.yml up -d
docker-compose -f docker-compose.test.yml up
docker-compose -f docker-compose.yml down