When `depends_on` is being used in docker-compose.yml? - docker-compose

When depends_on is being used in docker-compose.yml?
When a web app has connection to a database, in the docker compose yml file, I see these two examples. One is with depends_on and one is without depends_on.
In one tutorial, I see that there is no depends_on is being used.
version: '3'
services:
ms-sql-server:
image: mcr.microsoft.com/mssql/server:2017-latest-ubuntu
environment:
ACCEPT_EULA: "Y"
SA_PASSWORD: "xxxx"
ports:
- "1433:1433"
book-app:
build: .
ports:
- "8090:80"
In another example, I see that depends_on is being used.
version: "3"
services:
api:
build:
context: ..
dockerfile: CF.Api/Dockerfile
ports:
- "8888:80"
depends_on:
- db
db:
image: "mcr.microsoft.com/mssql/server"
environment:
SA_PASSWORD: "xxxx"
ACCEPT_EULA: "Y"

First, let's understand what depends_on means. The docs:
Based on that description, it's clear that in your second example, namely
version: "3"
services:
api:
build:
context: ..
dockerfile: CF.Api/Dockerfile
ports:
- "8888:80"
depends_on:
- db
db:
image: "mcr.microsoft.com/mssql/server"
environment:
SA_PASSWORD: "xxxx"
ACCEPT_EULA: "Y"
depends_on specifies that the api will need the db, so db as a service needs to be started before api, when docker-compose up is being executed.
Also, if docker-compose api is being executed, that will also start the db service before the api service is started. Also, docker-compose stop will first stop the api and only then stop the db service.
So, first db is started as a service and then api is started as a service as well. Note, that it is possible that api is started before db is ready.

Related

DOCKER_Cannot run multiple services by docker-compose

I'm set up docker compose for my project with 2 services: spring-boot and postgresql. I created Dockerfile and docker-compose,yml as below:
Dockerfile :
FROM openjdk:8-jdk-alpine
MAINTAINER linhan.com
COPY target/LinhAn-0.0.1-SNAPSHOT.jar linhan-server-1.0.0.jar
ENTRYPOINT ["java","-jar","/linhan-server-1.0.0.jar"]
docker-compose.yml:
version: '2'
services:
spring_boot:
image: 'linhan'
build: .
container_name: api
ports:
- "8080:8080"
depends_on:
- postgres
environment:
- SPRING_DATASOURCE_URL=jdbc:jdbc:postgresql://localhost:5432/test_db
- SPRING_DATASOURCE_USERNAME=user
- SPRING_DATASOURCE_PASSWORD=123456
- SPRING_JPA_HIBERNATE_DDL_AUTO=update
postgres:
image: 'postgres:13.1-alpine'
container_name: db
environment:
- POSTGRES_USER=user
- POSTGRES_PASSWORD=123456
Then, when I type docker-compose up in terminal, postgres ran only, spring boot still not.
I searched google for solution but seems no hope. Please help me, thanks a lot!!!!!
I think you need to change the SPRING_DATASOURCE_URL to reference your service name instead of localhost. The service name is resolved automatically to your service since all services are part of the default_network by default in docker-compose.
- SPRING_DATASOURCE_URL=jdbc:jdbc:postgresql://postgres:5432/test_db
Also, for clarity I would suggest you add the port to your docker-compose postgres service, so it is clear which port is being used, even if it is the default:
postgres:
image: 'postgres:13.1-alpine'
container_name: db
ports:
- "5432"
environment:
- POSTGRES_USER=user
- POSTGRES_PASSWORD=123456
Also, another suggestion would be to try and use a healthcheck to see if your database service becomes available instead of a simple depends_on. The short version will mark the dependency fulfilled as soon as the container is Running, regardless of the availability of the database.
Either that, or you can add application logic to retry database connection in case of failure.

Docker Compose - Service name not working as environment variable

I'm trying to use docker-compose to setup a Spring Cloud project.
I'm using spring cloud configuration so I have a Configuration Server and some services.
For now, I have 3 services in my docker-compose.yml
version: '3'
services:
db:
image: mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: 'root' # TODO: Change this
MYSQL_USER: 'user'
MYSQL_PASS: 'password'
MYSQL_ROOT_HOST: '%'
volumes:
- "db:/opt/mysql/docker:rw"
ports:
- "3307:3306"
config:
image: config-server
restart: always
depends_on:
- db
environment:
- SPRING_DATASOURCE_URL=jdbc:mysql://db:3306/ec_settings?createDatabaseIfNotExist=true&useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC
ports:
- "8100:8100"
gateway:
image: gateway
restart: always
depends_on:
- config
environment:
- CONFIG_URI=http://config:8100
ports:
- '8081:8080'
volumes:
db: {}
In gateway microservice, in bootstrap.yml, i have this setting
spring:
cloud:
config:
uri: ${CONFIG_URI}
When i put up the docker composer i see that gateway service is trying to fetch configuration from http://config:8100
Fetching config from server at : http://config:8100
So, the variable passes to Spring Boot but docker-compose does not replace the service name with its actual link.
The very strange thing is that SPRING_DATASOURCE_URL environment variable gets translated correctly in config service to connect to db service.
I finally solved it thanks to this link Docker - SpringConfig - Connection refused to ConfigServer
The problem was the service was trying to fetch the config url too early.
Solution is to put in bootstrap.yml this settings
spring:
cloud:
config:
fail-fast: true
retry:
max-attempts: 20

How can i link mongodb with other services in docker-compose?

i got a problem.
I made a docker-compose that runs mongo and node.
The problem is there is no way i use mongo from the container, i cannot start my node server.
Here there is my docker-compose :
version: '3'
services:
database:
build: ./Database
container_name: "dashboard_database"
ports:
- "27017:27017"
backend:
build: ./Backend
container_name: "dashboard_backend"
ports:
- "8080:8080"
depends_on:
- database
links:
- database
But when i start mongo without the container my node can reach it, i don't know why ...
Any idea ?
Thanks !
Dont define ports in the DB service. But afterwards only application will be able to access DB. Most probably it will work then. If you still want to access it from your PC then you should define a network. Try this
version: '3'
services:
database:
build: ./Database
container_name: "dashboard_database"
backend:
build: ./Backend
container_name: "dashboard_backend"
ports:
- "8080:8080"
depends_on:
- database
links:
- database
And for creating network
version: '3'
networks:
back-tier:
services:
database:
build: ./Database
container_name: "dashboard_database"
networks:
- back-tier
ports:
- "27017:27017"
backend:
build: ./Backend
container_name: "dashboard_backend"
networks:
- back-tier
ports:
- "8080:8080"
depends_on:
- database
All services in docker-compose are within the docker-compose created network, and can be addressed by their service names from other services. In your case the service names are database and backend, so for instance the database can be accessed by the backend with something like tcp://database:27017. You don't need to link them anymore.
https://runnable.com/docker/docker-compose-networking
Be aware depends_on only waits until the process has been started and does not wait for the process to be ready to accept connections.
https://docs.docker.com/compose/compose-file/#depends_on
https://docs.docker.com/compose/startup-order
The port mappings are only necessary if you want to make a service accessible from the local machine. In your examplte the backend service is accessible via localhost:8080.
If you want an external container to access a docker-compose service tne localhost:8080 wont work because localhost in the container isn't the same localhost as on your local machine where docker containers are running. You can create manually a docker network and connect the container and docker-compose services to it. See docker-compose-networking link and take a look at section Pre-existing Networks.
Does that help you?

How to add new port to one of docker-compose services without restarting all of them?

I have 'docker-compose.yml' file like below (skipped only volumes. environment and network). I would like to add new port to 'logstash' service without restarting all 3 services. I did 'docker-compose build logstash --no-cache' but it didn't add the port
docker#ubuntu-elastic:~/docker-elk$ cat docker-compose.yml
version: '2'
services:
elasticsearch:
build:
context: elasticsearch/
ports:
- "9200:9200"
- "9300:9300"
logstash:
build:
context: logstash/
ports:
- "11514:11514/udp"
- "8514:8514/udp"
depends_on:
- elasticsearch
kibana:
build:
context: kibana/
ports:
- "5601:5601"
depends_on:
- elasticsearch
This will do the trick:
docker-compose up -d logstash
If you do not change the other sections, this should also only update logstash:
docker-compose up -d
To make sure that only logstash gets updated, even if the other sections where updated too, use the first command.

How to initialize a database on a data volume container?

Here my simple scenario, I have a simple Flaskapp that connect to a postgres this way:
SQLALCHEMY_DATABASE_URI='postgresql://username:secretpassword#postgres:5432/myproj'
And I have a simple docker-compose.yml:
version: '2'
services:
postgres:
image: postgres:latest
volumes_from:
- data
environment:
POSTGRES_PASSWORD: secretpassword
POSTGRES_USER: username
POSTGRES_DB: myproj
ports:
- "5432:5432"
web:
build: .
volumes_from:
- app
ports:
- "5000:5000"
depends_on:
- postgres
data:
image: postgres:latest
volumes:
- /var/lib/postgresql/data
command: "true"
app:
build: .
volumes:
- .:/myproj
command: "true"
I need to lunch a made by myself flask script, that creates the tables for my app:
export FLASK_APP='./myproj/__init__.py'
flask createdbs
I have put these 2 operation in the Dockerfile of my web service but because my service and the postgres service have a depends_on relationship, the postgres db host is not available during the building phase.
Any suggestion on the best way to achieve this ? I want to avoid hacks, I would prefer respect a correct Docker workflow.
One way to do it is to use the "command" keyword:
https://docs.docker.com/compose/compose-file/#/command
(look also at entrypoint keyword)
web:
build: .
volumes_from:
- app
ports:
- "5000:5000"
depends_on:
- postgres
command: "export FLASK_APP='./myproj/__init__.py' && flask createdbs"
or using command just to launch your flask script and let your export in your dockerfile.
Note that "depends_on" only start one container before the other, but do not wait your postgres database to be ready. If you want to wait until postgres is ready to answer, you can use scripts like "wait-for-it.sh postgres:5432" that are well explained in docker-compose doc: https://docs.docker.com/compose/startup-order/