6) Data Generator on Docker Compose
Chapter Preview
목표
- DB 컨테이너와 Data Generator 컨테이너를 함께 띄우기 위한 Docker Compose 파일을 작성합니다.
- DB 안에 데이터가 계속해서 삽입되고 있는지 확인합니다.
스펙 명세서
Docker Compose 파일을 작성합니다.
- Postgres Server
- Service name :
postgres-server
- Image :
postgres:14.0
- Container name :
postgres-server
- Environment
- POSTGRES_USER :
myuser
- POSTGRES_PASSWORD :
mypassword
- POSTGRES_DB :
mydatabase
- POSTGRES_USER :
- Port forwarding :
5432:5432
- Service name :
- Data Generator
- Service name :
data-generator
- Image :
Dockerfile
- Container name :
data-generator
- Command :
["postgres-server"]
- Service name :
정보Postgres Server 서비스와 Data Generator 서비스를 띄울 때 어떤 서비스가 먼저 생성되어야 하는지 생각해보고, 그 기능을 Compose 파일에 추가합니다.
- Postgres Server
Docker Compose 파일을 실행합니다.
psql
을 이용하여 DB 에 데이터가 계속해서 쌓이고 있는지 확인합니다.- Local 에서 확인합니다.
- Data Generator server 에서 확인합니다.
해당 파트의 전체 코드는 mlops-for-mle/part1/ 에서 확인할 수 있습니다.
part1
├── Dockerfile
├── Makefile
├── create_table.py
├── data_generator.py
├── docker-compose.yaml
├── insert_data.py
└── insert_data_loop.py
0. 환경 설정
📌 이번 챕터에서는 Docker Compose 를 이용하여 컨테이너를 띄우는 법에 대해서 실습합니다.
📌 이를 위해서 앞서 1) DB Server Creation 챕터와 5) Data Generator on Docker 챕터에서 시작한 컨테이너를 종료해야 합니다.
다음 명령어를 통해 실행중인 DB 서버와 Data Generator 를 종료시킵니다.
docker rm --force postgres-server data-generator
1. Dockerfile
5) Data Generator on Docker 챕터에서 작성한Dockerfile
을 사용합니다.FROM amd64/python:3.9-slim
RUN apt-get update && apt-get install -y \
postgresql-client \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /usr/app
RUN pip install -U pip &&\
pip install scikit-learn pandas psycopg2-binary
COPY data_generator.py data_generator.py
ENTRYPOINT ["python", "data_generator.py", "--db-host"]
# Change CMD to solve host finding error
CMD ["localhost"]
2. Docker Compose
이제 Compose 파일을 작성해보도록 하겠습니다.
Compose 파일의 아키텍처는 아래와 같습니다.
version: "3"
services:
postgres-server:
...
data-generator:
...
- version :
- Compose 파일의 버전을 의미합니다. 최신 버전은 공식 홈페이지에서 확인하실 수 있습니다.
- 이번 챕터에서는 작성일 기준 최신 버전인
3
을 사용하겠습니다.
- services :
- Compose 에 묶일 서비스들을 의미합니다. 하나의 서비스는 하나의 컨테이너를 의미합니다.
- postgres-server : 01) DB Server Creation 챕터에서 사용한 DB 서버를 실행시키기 위한 내용을 정의할 서비스 이름입니다.
- data-generator : 05) Data Generator on Docker 챕터에서 사용한 Data Generator 를 실행시키기 위한 내용을 정의할 서비스 이름입니다.
이제 데이터를 저장할 postgres server 서비스와 데이터를 생성할 Data Generator 서비스를 작성해 보겠습니다.
2.1 Postgres Server Service
먼저, postgres-server
서비스를 아래와 같이 yaml 형태로 작성합니다.
postgres-server
서비스에서 사용하는 값들은 01) DB Server Creation 챕터에서 사용한 값과 같은 값을 사용합니다.
version: "3"
services:
postgres-server:
image: postgres:14.0
container_name: postgres-server
ports:
- 5432:5432
environment:
POSTGRES_USER: myuser
POSTGRES_PASSWORD: mypassword
POSTGRES_DB: mydatabase
- postgres-server :
- 서비스의 이름입니다.
- 입력한 이름은 실행되는 컨테이너의 호스트 이름이 됩니다.
- image :
- 사용할 컨테이너의 이미지를 입력합니다.
- ports :
- 컨테이너에서 외부로 노출할 포트 포워딩을 설정합니다.
- 형식은
host:container
로 사용되며 여러 개를 지정할 수 있습니다.
- environment :
- 컨테이너를 실행할 때 사용한
-e
옵션과 같은 역할을 합니다.
- 컨테이너를 실행할 때 사용한
2.2 Data Generator Service
다음으로, data-generator
서비스를 아래와 같이 yaml 형태로 작성합니다.
postgres-server
서비스와 다르게 이번에는 직접 이미지를 build 해서 사용합니다.
data-generator:
build:
context: .
dockerfile: Dockerfile
container_name: data-generator
depends_on:
- postgres-server
command: ["postgres-server"]
- build :
- context : 이미지를 build 하기 위해 Dockerfile 이 있는 절대경로 또는 상대경로를 설정합니다.
- dockerfile : context 에서 설정한 경로에 있는 Dockerfile 의 파일명을 입력합니다.
- depends_on :
- Compose 로 띄워지는 서비스 간의 종속성 순서대로 서비스를 시작할 때 사용합니다.
- 여기서는 postgres server 가 먼저 실행되고 난 뒤에 Data Generator 를 실행해야 하기 때문에 postgres server 의 서비스 이름인
postgres-server
를 입력합니다.
- command :
- Dockerfile 에 작성되어 있는
CMD
를 덮어씁니다. - 5) Data Generator on Docker 챕터에서 작성한 Data Generator 를 사용하기 위해서는 postgres server 의 호스트를 변경해야 합니다.
- 호스트 이름은 위에서 언급한 것처럼 컨테이너의 이름으로 주어야 하기 때문에
["postgres-server"]
로 덮어씁니다.
- Dockerfile 에 작성되어 있는
2.3 Docker Compose Healthcheck
앞서 작성한 docker-compose.yaml
파일의 내용을 함께 나열하면 아래와 같습니다.
version: "3"
services:
postgres-server:
image: postgres:14.0
container_name: postgres-server
ports:
- 5432:5432
environment:
POSTGRES_USER: myuser
POSTGRES_PASSWORD: mypassword
POSTGRES_DB: mydatabase
data-generator:
build:
context: .
dockerfile: Dockerfile
container_name: data-generator
depends_on:
- postgres-server
command: ["postgres-server"]
이제 작성한 Compose 파일을 실행해보겠습니다.
Compose 파일은 up
명령어와 down
명령어를 통해 실행과 종료를 할 수 있습니다.
docker compose up -d
- -d :
- Detached 모드로 실행합니다. Detached 모드란, 백그라운드에서 컨테이너를 실행 후 유지시키는 모드를 의미합니다.
하지만 docker ps
를 입력해보면 postgres server 만 띄워져있습니다.
하드웨어 스펙에 따라 따라 해당 내용이 재현이 안 되는 경우도 있습니다.
재현이 안되는 경우, 전체 흐름에 초점을 맞춰서 봐주시면 될 것 같습니다.
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8a4a16837f28 postgres:14.0 "docker-entrypoint.s…" About a minute ago Up About a minute 0.0.0.0:5432->5432/tcp postgres-server
Docker desktop 으로 봐도 동일한 현상입니다.
[그림 1-5] Docker Desktop
왜 이럴까요?
이유는 앞서 depends_on
으로 서비스 간의 종속성은 정했지만, 실제로 postgres server 가 띄워진 뒤에 곧바로 Data Generator 가 띄워집니다.
Postgres server 는 아직 준비가 되어있지 않은데 Data Generator 가 띄워져서 DB 에 연결을 하려다보니 Data Generator 가 Exited 되는 문제가 발생한 것입니다.
따라서 postgres server 가 사용 가능한 상태가 되어있는지 체크를 한 뒤에 Data Generator 를 띄워야 합니다.
이를 해결하기 위한 방법으로 Docker Compose Healthcheck 가 있습니다.
간단하게 아래와 같이 yaml 파일에 healthcheck
부분과 condition
을 추가하면 됩니다.
version: "3"
services:
postgres-server:
image: postgres:14.0
container_name: postgres-server
ports:
- 5432:5432
environment:
POSTGRES_USER: myuser
POSTGRES_PASSWORD: mypassword
POSTGRES_DB: mydatabase
healthcheck:
test: ["CMD", "pg_isready", "-q", "-U", "myuser", "-d", "mydatabase"]
interval: 10s
timeout: 5s
retries: 5
data-generator:
build:
context: .
dockerfile: Dockerfile
container_name: data-generator
depends_on:
postgres-server:
condition: service_healthy
command: ["postgres-server"]
- test :
- 테스트 할 명령어를 설정합니다.
- 이번 챕터에서는
pg_isready
를 이용하여 DB 가 준비상태인지 테스트를 진행하기 때문에["CMD", "pg_isready", "-q", "-U", "myuser", "-d", "mydatabase"]
를 입력합니다.
- interval :
- Healthcheck 간격을 설정합니다.
- 이번 챕터에서는 10초로 설정합니다.
- timeout :
- Healthcheck 의 timeout 을 설정합니다.
- 이번 챕터에서는 5초로 설정합니다.
- retries :
- Timeout 의 횟수를 설정합니다.
- 이번 챕터에서는 5번으로 설정합니다.
- condition :
- Healthcheck 기능을 사용하기 위해 depends_on 의 parameter 로
condition: service_healthy
를 넣어줍니다. - Postgres server 의 healthcheck 를 Data Generator 에서 적용시키기 위해
postgres-server
밑에 condition 을 추가하였습니다.
- Healthcheck 기능을 사용하기 위해 depends_on 의 parameter 로
이렇게 설정된 것을 종합해보면, 10초마다 테스트를 실행했을 때 5초 이내에 DB 가 준비 상태가 되었는지를 체크할 것이며, 실패 시 5번 재시도한다는 뜻이 됩니다. 이외에 더 자세한 내용은 Dockerfile Reference 을 참고해주시기 바랍니다.
이제 다시 서비스들을 실행해보겠습니다.
docker compose up -d
문제없이 잘 실행되는 것을 확인할 수 있습니다.
2.4 Docker Compose Network
2.4.1 Default Network
5) Data Generator on Docker 챕터에서 컨테이너들끼리 네트워크를 연결하는 부분을 설명했었습니다. 위의 서비스를 실행한 후 생성된 네트워크를 확인해 보겠습니다.docker network ls
실행하면 다음과 같이 part1_default
라는 이름의 네트워크가 생성된 것을 확인할 수 있습니다.
NETWORK ID NAME DRIVER SCOPE
d2a7834f5caa bridge bridge local
d7d45bd4c3b7 part1_default bridge local
0d5dc37e7a9d host host local
703a7cd222a5 none null local
part1_default
를 확인해 보겠습니다.
docker network inspect part1_default
네트워크에 자동으로 postgres-server
와 data-generator
컨테이너가 추가된 것을 볼 수 있습니다.
[
{
"Name": "part1_default",
...
"ConfigOnly": false,
"Containers": {
"4043d0d2df3673a5fac77945bb7746e1af4b352fb7617891de0b22357a877c59": {
"Name": "postgres-server",
...
},
"4ffdc089e4a40727645a0cab1952c025cdd583031f3ce7867761305ead2a6d63": {
"Name": "data-generator",
...
}
...
}
]
이처럼 Compose 파일을 사용하면 네트워크에 대해서 신경쓰지 않고 편리하게 컨테이너들을 연결해서 사용할 수 있습니다.
2.4.2 Custom Network
네트워크의 이름은 특별히 지정하지 않을 경우 {디렉토리명}_default
로 자동으로 생성이 됩니다.
그렇기 때문에 서로 같은 디렉토리를 사용하지 않을 경우 네트워크의 이름이 변할 수 있습니다.
앞으로 이어지는 파트에서는 서로 네트워크의 연결이 필요하기 때문에 이름을 지정해서 생성하겠습니다.
먼저 실행한 서비스들을 종료하겠습니다.
docker compose down -v
- -v :
- 생성된 볼륨까지 삭제합니다.
네트워크 생성은 services
와 같은 레벨에 networks
를 입력하면 됩니다.
networks:
default:
name: mlops-network
- default : 서비스 전체의 기본 네트워크를 수정할 수 있습니다.
- name : 네트워크의 이름을 작성합니다. 앞으로 이어지는 파트에서도 사용할 수 있도록
mlops-network
로 작성하겠습니다.
- name : 네트워크의 이름을 작성합니다. 앞으로 이어지는 파트에서도 사용할 수 있도록
2.4.3 실행
네트워크까지 작성한 최종 Compose 파일은 다음과 같습니다.
version: "3"
services:
postgres-server:
image: postgres:14.0
container_name: postgres-server
ports:
- 5432:5432
environment:
POSTGRES_USER: myuser
POSTGRES_PASSWORD: mypassword
POSTGRES_DB: mydatabase
healthcheck:
test: ["CMD", "pg_isready", "-q", "-U", "myuser", "-d", "mydatabase"]
interval: 10s
timeout: 5s
retries: 5
data-generator:
build:
context: .
dockerfile: Dockerfile
container_name: data-generator
depends_on:
postgres-server:
condition: service_healthy
command: ["postgres-server"]
networks:
default:
name: mlops-network
다시 docker compose
를 실행해 보겠습니다.
docker compose up -d
실행 후 네트워크를 확인합니다.
docker network ls
다음과 같이 mlops-network
가 추가된 것을 확인할 수 있습니다.
NETWORK ID NAME DRIVER SCOPE
d2a7834f5caa bridge bridge local
0d5dc37e7a9d host host local
e9671c141955 mlops-network bridge local
703a7cd222a5 none null local
3. 데이터 확인
3.1 In Local
psql
을 이용하여 DB 에 접속하고, 계속해서 데이터가 삽입되고 있는지 확인합니다.
PGPASSWORD=mypassword psql -h localhost -p 5432 -U myuser -d mydatabase
psql (14.3, server 14.0 (Debian 14.0-1.pgdg110+1))
Type "help" for help.
mydatabase=# select * from iris_data;
id | sepal_length | sepal_width | petal_length | petal_width | target
----+--------------+-------------+--------------+-------------+--------
1 | 6 | 2.9 | 4.5 | 1.5 | 1
2 | 6.9 | 3.1 | 5.4 | 2.1 | 2
3 | 5.1 | 3.7 | 1.5 | 0.4 | 0
4 | 6.3 | 2.7 | 4.9 | 1.8 | 2
5 | 4.4 | 2.9 | 1.4 | 0.2 | 0
6 | 4.7 | 3.2 | 1.3 | 0.2 | 0
3.2 In Data Generator Container
docker exec
를 이용하여 Data Generator 컨테이너 안으로 접속합니다.
docker exec -it data-generator /bin/bash
그리고 psql
을 이용하여 DB 로 접속합니다.
이 때 local 이 아닌 Data Generator 컨테이너에서 접속해야 하기 때문에 호스트를 localhost
에서 postgres-server
로 변경합니다.
PGPASSWORD=mypassword psql -h postgres-server -p 5432 -U myuser -d mydatabase
psql (13.8 (Debian 13.8-0+deb11u1), server 14.0 (Debian 14.0-1.pgdg110+1))
WARNING: psql major version 13, server major version 14.
Some psql features might not work.
Type "help" for help.
mydatabase=# select * from iris_data;
id | sepal_length | sepal_width | petal_length | petal_width | target
----+--------------+-------------+--------------+-------------+--------
1 | 6 | 2.9 | 4.5 | 1.5 | 1
2 | 6.9 | 3.1 | 5.4 | 2.1 | 2
3 | 5.1 | 3.7 | 1.5 | 0.4 | 0
4 | 6.3 | 2.7 | 4.9 | 1.8 | 2
5 | 4.4 | 2.9 | 1.4 | 0.2 | 0
6 | 4.7 | 3.2 | 1.3 | 0.2 | 0