I have the following docker-compose.yml.
version: "3.1"
services:
db:
container_name: ${MYSQL_CONTAINER}
image: mysql:5.7.30
volumes:
- ${VOLUMES_DIR}/mysql_data:/var/lib/mysql
- ./slow_log.cnf:/etc/mysql/my.cnf
- ${VOLUMES_DIR}/mysql_logs:/var/log/mysql
environment:
- MYSQL_ROOT_PASSWORD=${MYSQL_PASSWORD}
- MYSQL_USER=${MYSQL_USER}
ports:
- ${MYSQL_PORT}:3306
entrypoint: ""
command: bash -c "chown -R mysql:mysql /var/log/mysql && exec /entrypoint.sh mysqld --default-authentication-plugin=mysql_native_password"
restart: on-failure
backend:
container_name: ${BACKEND_CONTAINER}
image: ${BACKEND_IMAGE}
depends_on:
- db
ports:
- ${BACKEND_PORT}
command: >
bash -c "command A
&& command B
&& ... "
restart: unless-stopped
I am scaling backend service so my startup command is sudo docker-compose -p ${COMPOSE_PROJECT_NAME} up -d --scale backend=10.
The problem I am facing is command A, command B in service backend was running for all 10 containers startup(means they were being run 10 times).
But I want command A to run only once for all the backend service-related containers but Command B should run for all containers.
Any suggestions in accomplishing this?
I'm not entirely sure that there would be an out-of-the-box solution for your requirement.
However, I can suggest you a workaround like this. You can duplicate your backend service in docker-compose and run one backend service with both Command A and Command B, while the other backend has only Command B.
Then when you want to scale, you scale the backend which has only Command B.
version: "3.1"
services:
db:
container_name: ${MYSQL_CONTAINER}
image: mysql:5.7.30
volumes:
- ${VOLUMES_DIR}/mysql_data:/var/lib/mysql
- ./slow_log.cnf:/etc/mysql/my.cnf
- ${VOLUMES_DIR}/mysql_logs:/var/log/mysql
environment:
- MYSQL_ROOT_PASSWORD=${MYSQL_PASSWORD}
- MYSQL_USER=${MYSQL_USER}
ports:
- ${MYSQL_PORT}:3306
entrypoint: ""
command: bash -c "chown -R mysql:mysql /var/log/mysql && exec /entrypoint.sh mysqld --default-authentication-plugin=mysql_native_password"
restart: on-failure
backend_default:
container_name: ${BACKEND_CONTAINER}
image: ${BACKEND_IMAGE}
depends_on:
- db
ports:
- ${BACKEND_PORT}
command: >
bash -c "command A
&& command B
&& ... "
restart: unless-stopped
backend:
container_name: ${BACKEND_CONTAINER}
image: ${BACKEND_IMAGE}
depends_on:
- db
ports:
- ${BACKEND_PORT}
command: >
bash -c "command B
&& ... "
restart: unless-stopped
Now you can use the scale option like below:
sudo docker-compose -p ${COMPOSE_PROJECT_NAME} up -d --scale backend=9
Now if there happens to be a scenario, where you need only 1 backend to be run, you can use profiles in docker-compose to only run backend when there is a specific profile is given with docker-compose command. That means only default_backend will run if that profile is not given and hence the scale is 1.
Hope this helps you. Cheers 🍻 !!!
If BACKEND_IMAGE is being built by you, you should do RUN command A in your Dockerfile. The RUN line will be executed only once during build time — so you will also need to make sure that this meshes with your needs — while the ENTRYPOINT and CMD lines will only be run upon execution of the container. The command in the docker-compose file overrides the CMD line.
Related
I am attempting to use the docker-compose.yml from the Rails example on the Docker site. This is a Windows (WSL2/Ubuntu/Docker Desktop) machine, so any files created in the docker container are owned by root. I am trying to pass my user id and group id as args, but I can't figure out a syntax that will let me:
version: "3.9"
services:
db:
image: postgres
volumes:
- ./tmp/db:/var/lib/postgresql/data
environment:
POSTGRES_PASSWORD: password
web:
build:
context: .
args:
- USER_ID=$(id -u)
- GROUP_ID=$(id -g)
command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
volumes:
- .:/myapp
ports:
- "3000:3000"
depends_on:
- db
The ideal is to have one process per container, but there is a strong affinity between Flask+uwsgi and Nginx.
Currently we run them together, but should we refactor ?
Yes, it's a good idea to refactor. Try to make service ephemeral and run only one main process in it. So, in the end, you need to have something like this:
version: '3.4'
services:
web:
build:
dockerfile: Dockerfile
context: .
ports:
- 8000:8000
volumes:
- .:/app/
env_file:
- common.env
nginx:
restart: always
image: nginx:1.18-alpine
ports:
- 80:80
- 443:443
volumes:
- ./deployment/nginx.conf:/etc/nginx/conf.d/default.conf
- ./deployment/config.conf:/etc/nginx/nginx.conf
command: "/bin/sh -c 'while :; do sleep 6h & wait $${!}; nginx -s reload; done & nginx -g \"daemon off;\";'"
depends_on:
- web
It's designed to have only one main process in a container, in that case if your application fails the container will be down.
I try i setup a Shopware Docker Container for development. I setup a Dockerfile for the Shopware initialize process but every time i run the build process shopware return this error message:
mysql -u 'root' -p'root' -h 'dbs' --port='3306' -e "DROP DATABASE IF EXISTS `shopware6dev`"
ERROR 2005 (HY000): Unknown MySQL server host 'dbs' (-2)
i think docker setup the default network after all build processes are done but i need to connect before all containers are ready. The depends_on option brings nothing. I hope anyone have a idea to solve this problem.
This is my docker-compose file:
version: '3'
services:
shopwaredev:
build:
context: ./docker/web
dockerfile: Dockerfile
volumes:
- ./log:/var/log/apache2
environment:
- VIRTUAL_HOST=shopware6dev.test,www.shopware6dev.test
- HTTPS_METHOD=noredirect
restart: on-failure:10
depends_on:
- dbs
adminer:
image: adminer
restart: on-failure:10
ports:
- 8080:8080
dbs:
image: "mysql:5.7"
volumes:
- ./mysql57:/var/lib/mysql
environment:
- MYSQL_ROOT_PASSWORD=root
- MYSQL_DATABASE=shopware6dev
restart: on-failure:10
nginx-proxy:
image: solution360/nginx-proxy
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- ./ssl:/etc/nginx/certs
restart: on-failure:10
and this is my dockerfile for web shopwaredev container:
FROM solution360/apache24-php74-shopware6
WORKDIR /var/www/html
RUN rm index.html
RUN git clone https://github.com/shopware/development.git .
RUN cp .psh.yaml.dist .psh.yaml
RUN sed -i 's|DB_USER: "app"|DB_USER: "root"|g' .psh.yaml
RUN sed -i 's|DB_PASSWORD: "app"|DB_PASSWORD: "root"|g' .psh.yaml
RUN sed -i 's|DB_HOST: "mysql"|DB_HOST: "dbs"|g' .psh.yaml
RUN sed -i 's|DB_NAME: "shopware"|DB_NAME: "shopware6dev"|g' .psh.yaml
RUN sed -i 's|APP_URL: "http://localhost:8000"|APP_URL: "http://shopware6dev.test"|g' .psh.yaml
RUN ./psh.phar install
My docker-compose.yml
version: '3.1'
services:
redis:
container_name: redis
image: redis:3.0
app_prod:
container_name: app_prod
build:
dockerfile: .docker/app/prod.Dockerfile
context: ./../
ports:
- "8080:80"
links:
- mysql:mysql
- redis:redis
depends_on:
- mysql
- redis
environment:
PRODUCTION_MODE: 'true'
entrypoint: .docker/app/sh/entry-point.sh
mysql:
image: mysql
command: --default-authentication-plugin=mysql_native_password
restart: always
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: 'my-db'
build:
context: ./mysql # path to folder containing Dockerfile
My .docker/app/sh/entry-point.sh
#!/usr/bin/env bash
set -e # exit script if any command fails (non-zero value)
echo Waiting for redis service start...;
while ! nc -z redis 6379;
do
sleep 1;
done;
echo Waiting for mysql service start...;
while ! nc -z mysql 3306;
do
sleep 1;
done;
echo Connected!;
php www/index.php orm:schema-tool:update --force
exec "$#"
I am building by command:
docker-compose -f .docker/docker-compose-prod.yml up -d --build
All containers are built successfully but at the end is running entrypoint script of container app_prod (.docker/app/sh/entry-point.sh). Entry point script was processed successfully too but after execute entrypoint script is app_prod container stopped.
It is some way to keep container running?
Thanks
Definitionally, no: once the entrypoint exits the container exits.
Your entrypoint is a shell script ending in exec "$#" (good!) which means that, after it successfully waits for its databases to be up, it will run whatever is passed in the docker-compose.yml as command:. (Note that if you declare entrypoint: in docker-compose.yml, it ignores a CMD in the Dockerfile.) So you just need a command: that starts your service and you should be set
entrypoint: .docker/app/sh/entry-point.sh
command: php-fpm
I know the question has been asked in various situations, but I'm still stucked despite everything I read on the Internet.
I want to have a script executed after the container "mywebsite" is built and I used ENTRYPOINT for that and I know that in normal use, after the ENTRYPOINT command is executed, the container "mywebsite" exit. I tried several tricks to avoid exit, unfortunately without success.
In my DOCKERFILE I have this :
FROM php:7.1.17-apache
[...]
WORKDIR /var/www
COPY docker-entrypoint.sh /var/www/docker-entrypoint.sh
ENTRYPOINT ["sh", "/var/www/docker-entrypoint.sh"]
Then in my docker-entrypoint.sh I have this :
#!/bin/bash
set -e
cd www
chown -R www-data:www-data sites modules themes
exec "$#"
And here is my docker-compose.yml :
version: '3.3'
services:
mywebsite:
build: .
extra_hosts:
- "mywebsite.local:127.0.0.1"
hostname: mywebsite
domainname: local
ports:
- 8088:80
volumes:
- ./www:/var/www/www
- ./vendor:/var/www/vendor
- ./scripts:/var/www/scripts
links:
- database:database
restart: always
tty: true
database:
image: mysql:5.5.49
container_name: mysql-container
ports:
- 3307:3306
volumes:
- ./www/dumps/mywebsite.sql:/docker-entrypoint-initdb.d/dump.sql
restart: always
command: --max_allowed_packet=32505856
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: mywebsite
When build, all steps are fine, and everything is set properly, but the container "mywebsite" keep exiting. (The "database" service is running fine)
I haded tty: true and exec "$#" but none of that works.
You can end with command like tail -f /dev/null
I often use this directly in my docker-compose.yml with command: tail -f /dev/null. And it is easy to see how I keep the container running.
I had the same problem when creating my own image from a postgis-image. The problem was that I added an entrypoint. When I removed the entrypoint, build the image again, docker-compose does start my container and postgis was accepting connections.
dockerfile
FROM postgis/postgis:12-master
COPY organisation.sql
#ENTRYPOINT ["docker-entrypoint.sh"] #This was the problem
In docker-compose I did not need command's or tty.
version: "3.7"
services:
mydb:
image: mydb:latest
container_name: mytest
ports:
- "5432:5432"
environment:
POSTGRES_DB: postgres
POSTGRES_USER: postgres
POSTGRES_PASSWORD: secret