CI/CD 맛보기 - Docker with local DB

dj-yang·2024년 2월 26일
0

CI/CD

목록 보기
2/2
post-thumbnail

이번에는 로컬 서버를 도커로 동작 시킬 생각이다. 이와 같은 생각을 했을 때 걱정되는 점은 사실 하나였다.

내가 개인적으로 사용하는 MySQL 서버가 Local에서 돌고 있는데, 이 데이터 베이스에 연결을 해서 어플리케이션을 동작 시키고 싶었다.


Docker

도커가 무엇인지에 대해서 검색해보면 아래와 같은 내용을 확인할 수 있었다.

도커는 리눅스의 응용 프로그램들을 프로세스 격리 기술들을 사용해 컨테이너로 실행하고 관리하는 오픈 소스 프로젝트이다. 도커 웹 페이지의 기능을 인용하면 다음과 같다: 도커 컨테이너는 일종의 소프트웨어를 소프트웨어의 실행에 필요한 모든 것을 포함하는 완전한 파일 시스템 안에 감싼다.

위의 내용 중에 중요한 부분은 격리 기술과 컨테이너가 아닐까 싶다. 도커는 조금 더 멋있는 설명이 있겠지만 내가 봤을 때는 이미지를 가져와 컨테이너처럼 사용할 수 있다.

장점은 내가 기존에 동작하는 서버와 같은 환경의 새로운 컴퓨터를 동작시킬 때, 굳이 새로운 설정이 필요 없다는 점이다. 그냥 기존에 있던 이미지를 불러와서 구동만 시키면 된다.

또, 패키지들의 디펜던시 관리 또한 용의하다고 판단하고 있다. 기존의 가상환경이랑 같은 역할을 하는 것처럼 느껴졌다.

Docker에 대해서는 아주 잘 정리 되어있으니 별도로 따로 다루지는 않겠다.


FastAPI

우리 팀의 사이드 프로젝트에서 서버는 fastAPI를 공부 겸 사용하기로 했다. 해당 프레임워크에서 Docker에 대한 기본 세팅 명령어를 제공해주고 있어, 우선 가져와봤다.

출처 - https://fastapi.tiangolo.com/deployment/docker/#dockerfile

FROM python:3.9

WORKDIR /code
 
COPY ./requirements.txt /code/requirements.txt
 
RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt
 
COPY ./app /code/app
 
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"]

이미 어느 정도 기능을 구현한 프로젝트이기 때문에 역시 정상적으로 동작하지는 않았다.
따라서 인터넷을 검색해서 나에게 맞게 몇가지를 수정했다. 수정한 사항은 아래와 같다.

  • Python 버전을 3.11로 올렸다.
  • 사용하고 있는 패키지 관리 툴이 Poetry이기 때문에 Poetry를 명시적으로 인스톨 해줬고, 그것을 Docker에도 전달했다.
  • uvicorn을 Poetry에서 관리하고 있음에도 불구하고 실행이 안되길래 찾아보니 명시적으로 선언을 해줘야한다고 해서 uvicorn 패키지를 별도로 인스톨해줬다.
  • mysql을 제대로 사용하기 위해서 mysql client를 설치했다.
FROM python:3.11

WORKDIR /code

# Install poetry
RUN pip install poetry

# Install MySQL client
RUN apt-get update && apt-get install -y default-mysql-client

# Copy pyproject.toml and poetry.lock
COPY pyproject.toml poetry.lock /code/

# Install dependencies using poetry
RUN poetry config virtualenvs.create false \
    && poetry install --no-root --no-dev

# Install uvicorn (if not included in pyproject.toml)
RUN pip install uvicorn

# Copy the rest of the application code
COPY . /code/

# Command to run the application
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"]

이렇게 Dockerfile을 구성해서 Docker run을 시켰지만 환경 변수 부분을 인식을 못해, 서버가 제대로 켜지지 않고 꺼지고 있었다.

로그를 확인해보니 환경변수가 동작하지 않아 문제가 발생하고 있어서 검색해보니 Docker Run Command를 줄 때 -e 옵션을 통해 환경 변수를 줄 수 있다고 해서 Command를 아래와 변경했다.

docker run -d --name mycontainer --network host \
-e MYSQL_USER={{MYSQL_USER}} \
-e MYSQL_PASSWORD={{MYSQL_PASSWORD}} \
-e MYSQL_HOST={{MYSQL_HOST}} \
-e MYSQL_DATABASE={{MYSQL_DATABASE}} \
-p 80:80 {{IMAGE_NAME}}

하지만, 정상적으로 동작하지 않았고 계속해서 같은 오류가 발생했다.

원인을 파악하기 위해 환경 변수가 docker에게 넘어가는 것이 아닌지 아니면 Value는 제대로 넘어갔지만 어플리케이션단까지 넘어가지 않고 있는 건지 체크가 필요했다.

main.py의 코드를 가장 베이스 코드로 변경하고 docker를 구동시키고 같은 명령어로 docker container를 실행했다.

docker exec -it  {{CONTAINER ID}} /bin/bash

위와 같이 동작하면 이제 제대로 된 환경변수가 적용되어 있는 지 아래와 같은 방식으로 확인해보면 된다.

echo $MYSQL_USER


내가 주입한 환경 변수가 제대로 나오는 것을 확인했지만 아직도 원인을 몰랐었다.

그러던 중 같이 문제를 해결해주던 지인이 --network option에서 의문을 제기했고, docker docs를 확인해본 결과...

...
The host networking driver only works on Linux hosts, and is not supported on Docker Desktop for Mac, Docker Desktop for Windows, or Docker EE for Windows Server.
...
출처 - https://docs.docker.com/network/drivers/host/

linux 환경에서만 host 모드를 지원한다는 글을 발견하여, network option을 제거하고 실행했더니 원하던대로 local db와 연결된 docker container가 열렸다.


network host mode

이때 host 모드에 대해서 조금 궁금해서 찾아봤는데. 내가 이해한 바로는 docker container는 별도의 네트워크 환경에서 동작하기 때문에 접속할 수 있는 포트를 연결해야하는데(위의 command에서 80:80 부분이 해당 역할을 하고 있다.) network 옵션을 host로 설정할 별도의 네트워크 설정 없이 내 서버 == 컨테이너에서 운영하는 서버가 되어 도커 내에서도 localhost라는 주소로 내 서버에 접속할 수 있는 것이라 생각한다.

참고로 우리는 host 모드가 아니기 때문에 도커에서 내 로컬에 접속해야한다면 host.docker.internal를 호스트로 설정하면 된다...!


다음은 도커 기반으로 자동 배포를 진행하는 방법을 진행해보려고 한다. 가능하다면 terraform이나 aws에서 제공하는 기능을 이용해서 환경변수 또한 안전하게 관리하는 것 또한 진행해볼까 한다.

profile
비전공자가 고통받으며 개발합니다

0개의 댓글