
이번 글에서는 예제를 통해 Dockerfile을 작성하고 실행하는 방법에 대해 알아보도록 하겠습니다. 예제는 https://mlops-for-mle.github.io/tutorial/을 학습하며 작성하였음을 미리 알려드립니다. 우선 예제의 시나리오는 PostgreSQL container는 이미 존재하는 상황이고, data_generator.py을 실행할 수 있는 container를 생성하여 iris 데이터를 PostgreSQL DB에 입력하는 것입니다.
data_generator.py 코드는 다음과 같습니다. 해당 코드는 python을 통해 iris 데이터를 DB에 입력하는 코드입니다. 자세한 설명은 넘어가도록 하겠습니다.
# data_generator.py
import time
from argparse import ArgumentParser
import pandas as pd
import psycopg2
from sklearn.datasets import load_iris
def get_data():
X, y = load_iris(return_X_y=True, as_frame=True)
df = pd.concat([X, y], axis="columns")
rename_rule = {
"sepal length (cm)": "sepal_length",
"sepal width (cm)": "sepal_width",
"petal length (cm)": "petal_length",
"petal width (cm)": "petal_width",
}
df = df.rename(columns=rename_rule)
return df
def create_table(db_connect):
create_table_query = """
CREATE TABLE IF NOT EXISTS iris_data (
id SERIAL PRIMARY KEY,
timestamp timestamp,
sepal_length float8,
sepal_width float8,
petal_length float8,
petal_width float8,
target int
);"""
print(create_table_query)
with db_connect.cursor() as cur:
cur.execute(create_table_query)
db_connect.commit()
def insert_data(db_connect, data):
insert_row_query = f"""
INSERT INTO iris_data
(timestamp, sepal_length, sepal_width, petal_length, petal_width, target)
VALUES (
NOW(),
{data.sepal_length},
{data.sepal_width},
{data.petal_length},
{data.petal_width},
{data.target}
);
"""
print(insert_row_query)
with db_connect.cursor() as cur:
cur.execute(insert_row_query)
db_connect.commit()
def generate_data(db_connect, df):
while True:
insert_data(db_connect, df.sample(1).squeeze())
time.sleep(1)
if __name__ == "__main__":
parser = ArgumentParser()
parser.add_argument("--db-host", dest="db_host", type=str, default="localhost")
args = parser.parse_args()
db_connect = psycopg2.connect(
user="myuser",
password="mypassword",
host=args.db_host,
port=5432,
database="mydatabase",
)
create_table(db_connect)
df = get_data()
generate_data(db_connect, df)
다음은 해당 python 파일을 실행하기 위한 Dockerfile을 작성해 보겠습니다. 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"]
- 1) FROM
- base가 되는 image를 설정하는 부분
- 해당 코드에서는 python 3.9 버전을 설치하고, 일반적인 python보다 가벼운 slim image를 사용 - 2) RUN
- image를 생성할 때 실행할 코드를 작성하는 부분
- apt-get : low-level 패키지 매니저로, 먼저 update를 진행하고 설치 과정에서의 확인 프롬프트에서 자동으로 y를 선택
- postgresql-client : psql을 실행하기 위해 설치
- rm -rf /var/lib/apt/lists/* : 해당 경로는 apt 패키지 관리 시스템이 사용하는 캐시 및 리스트 파일들이 위치한 디렉토리로, 해당 경로를 삭제하여 image 크기를 줄이고 불필요한 캐시를 방지 - 3) WORKDIR
- 작업 경로를 지정하는 부분으로, 이후 작업은 모두 해당 경로에서 진행
- 지정한 경로가 없을 경우 자동으로 경로 생성 - 4) RUN
- pip install -U pip : python 패키지 관리 매니저로, 먼저 update 진행
- pip install scikit-learn pandas psycopg2-binary : python 내 필요한 패키지 설치 - 5) COPY
- 파일 혹은 폴더를 생성하는 image에 복사하는 부분
- 절대 경로를 사용하지 않을 경우, 위에서 설정한 작업 경로에 복사 - 6) ENTRYPOINT
- 생성한 image를 바탕으로 container를 실행할 때, 진행하고자 하는 프로세스 작성
- space를 기준으로 명령어를 구분하여 작성 - 7) CMD
- ENTRYPOINT에서 실행되는 코드에 argument를 전달
해당 Dockerfile을 바탕으로 image를 build하는 명령어는 아래와 같습니다. -t 옵션은 image의 tag를 설정하는 부분이고, 마지막에 위치한 . 은 Dockerfile이 현재 경로에 위치한 것을 의미합니다.
$ docker build -t data-generator .
생성된 image를 그대로 실행할 경우, DB에 연결되지 않는다는 오류가 발생할 것입니다. 이는 이전에 생성한 PostgreSQL container와 지금 생성한 python 실행 container가 연결되어있지 않기 때문입니다. 이를 위해서는 두 container를 위한 network를 생성해줘야 합니다.
다음과 같이 network를 생성하고 PostgreSQL 서버에 연결해줍니다. 그리고 다음과 같은 명령어로 image를 실행하면, 정상적으로 작동하게 됩니다. 여기서 알아두면 좋은 점은 Dockerfile을 작성할 때 마지막 CMD에서 "localhost"를 지정하였지만, "postgre-server"와 같이 다른 서버를 입력해 주면 argument가 바뀌어 전달됩니다.
$ docker network create my-network
$ docker network connect my-network postgres-server
$ docker run -d \
--name data-generator \
--network "my-network" \
data-generator "postgres-server"
실무에서는 이런 방식으로 하기보다는 Docker compose를 통해 진행하게 됩니다. 다음 글에서는 Docker compose에 대해 설명하도록 하겠습니다.
<참고>
https://mlops-for-mle.github.io/tutorial/
MLOps for MLE | ML Engineer를 위한 MLOps
Description will go into a meta tag in <head />
mlops-for-mle.github.io
'MLOps > Docker' 카테고리의 다른 글
| [Docker] cannot stop container: permission denied 오류 해결 (0) | 2025.03.05 |
|---|---|
| [Docker] error getting credentials ~ 오류 해결 (0) | 2024.05.20 |
| [Docker] PostgreSQL 서버 생성 (0) | 2023.12.12 |
| [Docker] permission denied while trying to connect to the Docker daemon socket at unix 오류 해결 (2) | 2023.11.10 |
| [Docker] 자주 사용하는 명령어 정리 (0) | 2023.10.20 |
댓글