개요

Docker Compose를 사용할 때 서비스 간의 의존성을 제어하는 것은 매우 중요합니다. 특히 복잡한 애플리케이션에서 서비스의 시작 순서와 종료 순서를 관리하는 것은 필수적입니다. 해당 포스터에서는 서비스 의존성을 제어하는 다양한 방법과 예제를 살펴보겠습니다.

디렉토리 구조

다음과 같은 디렉토리 구조를 가정하고 진행하겠습니다. 만약에 설명 중에 별도의 언급이 없다면 이전파일과 동일하다고 가정합니다.

/
├── docker-compose.yml
├── go.mod 
└── web/
├──── Dockerfile
└──── main.go

depends_on 속성 사용하기

depends_on 속성은 서비스 간의 기본적인 의존성을 설정하는 데 사용됩니다.

  • web/main.go
 1package main
 2
 3import (
 4	"fmt"
 5	"net/http"
 6)
 7
 8func main() {
 9	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
10		fmt.Fprintf(w, "Hello, World!")
11	})
12	http.ListenAndServe(":8080", nil)
13}
  • web/Dockerfile
 1FROM golang:1.22
 2
 3WORKDIR /app
 4
 5COPY go.mod ./
 6COPY web/main.go ./
 7
 8RUN go mod tidy
 9
10RUN go build -o main .
11
12CMD ["./main"]
  • docker-compose.yml
 1version: '3.8'
 2
 3services:
 4  web:
 5    build:
 6      context: .
 7      dockerfile: web/Dockerfile
 8    ports:
 9      - "8080:8080"
10    depends_on:
11      - db
12  db:
13    image: postgres:13
14    environment:
15      POSTGRES_DB: mydb
16      POSTGRES_USER: user
17      POSTGRES_PASSWORD: password

위의 예제에서는 web 서비스가 db 서비스에 의존하도록 설정되어 있습니다. 따라서 docker-compose up 명령을 실행하면 db 서비스가 먼저 시작되고 web 서비스가 시작됩니다.

하지만 depends_on 속성은 서비스가 시작되는 것을 보장하지 않습니다. 기본적으로 depends_on은 의존하는 서비스의 컨테이너 상태가 running인지만 확인합니다. 따라서 서비스가 시작되는 것을 보장하려면 healthcheck을 사용해야합니다.

healthcheck을 사용하기

healthcheck을 사용하면 서비스가 시작되는 것을 보장할 수 있습니다.

  • web/main.go
 1package main
 2
 3import (
 4	"database/sql"
 5	"fmt"
 6	_ "github.com/lib/pq"
 7	"log"
 8	"net/http"
 9)
10
11func main() {
12	db, err := sql.Open("postgres", "postgres://user:password@db/mydb?sslmode=disable")
13	if err != nil {
14		log.Fatal(err)
15	}
16	defer db.Close()
17
18	// 데이터베이스 연결 확인
19	err = db.Ping()
20	if err != nil {
21		log.Fatal(err)
22	}
23
24	mux := http.NewServeMux()
25
26	mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
27		log.Printf("Received request for path: %s", r.URL.Path)
28		if r.URL.Path != "/" {
29			http.NotFound(w, r)
30			return
31		}
32		fmt.Fprintf(w, "Hello, World!")
33	})
34
35	mux.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) {
36		log.Printf("Received health check request")
37		err := db.Ping()
38		if err != nil {
39			log.Printf("Database health check failed: %v", err)
40			http.Error(w, "Database not available", http.StatusServiceUnavailable)
41			return
42		}
43		fmt.Fprintf(w, "OK")
44	})
45
46	log.Println("Server is running on :8080")
47	if err := http.ListenAndServe(":8080", mux); err != nil {
48		log.Fatal(err)
49	}
50}
  • docker-compose.yml
 1version: '3.8'
 2
 3services:
 4  web:
 5    build:
 6      context: .
 7      dockerfile: web/Dockerfile
 8    ports:
 9      - "8080:8080"
10    depends_on:
11      db:
12        condition: service_healthy
13  db:
14    image: postgres:13
15    environment:
16      POSTGRES_DB: mydb
17      POSTGRES_USER: user
18      POSTGRES_PASSWORD: password
19    healthcheck:
20      test: ["CMD-SHELL", "pg_isready -U user -d mydb"]
21      interval: 10s
22      timeout: 5s
23      retries: 5

정리

depends_on 속성을 사용하면 서비스 간의 기본적인 의존성을 설정할 수 있고, `healthcheck을 사용하면 서비스가 정상적으로 동작하는지 확인할 수 있습니다. docker-compose를 사용할 때는 보통 여러 컨테이너를 함께 실행하게 되는데 이런 의존성 관리를 잘 해야만 문제 없는 서비스를 운영할 수 있습니다. 해당 내용이 도움이 되었으면 좋겠습니다.