When I run docker compose up
, I’m expecting for my postgres_container to run before my go_container since the go_container is dependent on postgres_container as specified in the yml file depends_on
. However, my go_container is executed first and the postgres_container doesn’t seem to ever start.
docker-compose.yml
version: '3.8'
services:
go_container:
container_name: go_container
environment:
- DATABASE_USER=${DATABASE_USER}
- DATABASE_PASSWORD=${DATABASE_PASSWORD}
- DATABASE_NAME=${DATABASE_NAME}
- DATABASE_HOST=${DATABASE_HOST}
- DATABASE_PORT=${DATABASE_PORT}
- API_KEY=${API_KEY}
build: .
ports:
- 8080:8080
volumes:
- .:/src
depends_on:
- postgres_container
restart: on-failure
networks:
- weather
postgres_container:
container_name: postgres_container
user: postgres
image: postgres:latest
restart: always
environment:
- POSTGRES_USER=${DATABASE_USER}
- POSTGRES_DB=${DATABASE_NAME}
- POSTGRES_PASSWORD=${DATABASE_PASSWORD}
ports:
- 5432:5432
volumes:
- db_data:/var/lib/postgresql/data
- ./sql/create.sql:/docker-entrypoint-initdb.d/create.sql
healthcheck:
test: ["CMD-SHELL", "pg_isready", "-U", "${DATABASE_USER}"]
networks:
- weather
volumes:
db_data: {}
networks:
weather:
driver: bridge
Dockerfile
FROM golang:1.21.5
EXPOSE 8080
WORKDIR /src
COPY .env .
COPY . .
RUN go mod download && go mod verify
WORKDIR /src/cmd/app
RUN go run main.go
At first, my docker-compose.yml was respecting the depends_on
key but after some changes it stopped. Im not sure at what point it stopped working. I thought it was a bug in my docker installation so I tired reinstalling Docker but the problem persists.
.env file
DATABASE_HOST=postgres_container
DATABASE_PORT=5432
DATABASE_USER=postgres
DATABASE_PASSWORD=postgres
DATABASE_NAME=weather
SERVER_PORT=8080
Here are the logs:
docker log
2
Answers
The
depends_on
directive, as you’ve used it here, is almost entirely useless, because the dependency is only on container startup. That is,go_container
starts afterpostgres_container
has started, but that doesn’t mean that Postgres is actually ready to service connections.You can use the extended form of the
depends_on
directive to achieve the ordering you want. See this documentation; the resulting configuration would look something like:If we take a look at the logs, we see that the image build process fails. Looking closely at the containerfile, we see the following on the last line:
RUN
is executed at image buildtime, not container runtime. In contrast,depends_on
in thedocker-compose.yml
controls the order in which containers are started; it has no effect for image building.To fix this issue, we need to either use
CMD
(docs.docker.com
),ENTRYPOINT
(docs.docker.com
) or a combination of both to define the command. I will continue using theENTRYPONT
approach:Please also look at @larsks‘s answer. Their answer has a valid point with regards to startup order.
A remark: it is strange to use
go run ...
in a containerile to run the code. I would recommend compiling the code first, and then executing the result of the compilation. We can achieve this with a multi-stage build (docs.docker.com
). I also wrote a blog article discussing multi-stage containerfiles (turing85.github.io
). An example can be found here (github.com
).