Docker Compose中postgres_container未在go_container前启动问题
问题
执行docker compose up时,按配置go_container通过depends_on依赖postgres_container,本该先启动PostgreSQL容器再启动Go容器,但实际Go容器先执行,PostgreSQL容器完全没启动。之前相同配置是正常的,修改后失效,重装Docker也无法解决。
相关配置文件
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
.env
DATABASE_HOST=postgres_container DATABASE_PORT=5432 DATABASE_USER=postgres DATABASE_PASSWORD=postgres DATABASE_NAME=weather SERVER_PORT=8080
问题原因
核心问题出在Dockerfile里的RUN go run main.go:
RUN是镜像构建阶段执行的命令,而非容器启动阶段。执行docker compose up时,会优先构建Go服务的镜像,构建过程中就会运行go run main.go尝试启动应用,此时PostgreSQL容器还未创建,必然连接失败,导致构建卡住或失败,后续PostgreSQL容器根本没机会启动,看起来就像是Go容器先执行、PostgreSQL没启动。
解决方案
- 修正Dockerfile的启动命令
把RUN go run main.go替换为容器启动时执行的命令,比如CMD:
FROM golang:1.21.5 EXPOSE 8080 WORKDIR /src COPY .env . COPY . . RUN go mod download && go mod verify WORKDIR /src/cmd/app CMD ["go", "run", "main.go"]
这样构建镜像时不会启动应用,只有当容器真正启动时才会运行Go服务,此时depends_on会保证PostgreSQL容器先启动。
- 增强依赖检查(可选但推荐)
Docker Compose的depends_on仅保证容器启动顺序,不保证服务就绪。结合PostgreSQL的healthcheck,让Go容器等PostgreSQL服务真正就绪后再启动:
修改docker-compose.yml中go_container的depends_on:
depends_on: postgres_container: condition: service_healthy
- 清理旧镜像并重新构建
执行以下命令清理旧的镜像和容器,避免缓存影响:
docker compose down --rmi all docker compose up --build
内容的提问来源于stack exchange,提问作者Papilo
相关产品推荐
相关产品推荐

