이전 도커 이미지 최적화 과정 : https://www.inforum24.com/memos/1331
프로젝트에 새로 파이썬 패키지 shapely 를 도입하면서, 내부의 C 언어 구현체들을 컴파일 하기위해 시스템 라이브러리들이 필요했다. 배포 환경에서 시스템 라이브러리들도 같이 필요한 상황이였기 때문에 급하게 Dockerfile에 설치 명령어들을 추가했는데, docker image 가 328MB 에서 1.14 GB가 되었다. 다시 최적화해보자.
shapely 패키지가 필요한가?
가장 크게 이미지 사이즈 변화가 일어났다고 생각되는 부분은 shapely 패키지 및 시스템 라이브러리들이 같이 docker image 에 들어갔기 때문이라고 생각했다.
해당 패키지를 설치한 개발자에게 요청하여 shapely 패키지를 Mysql point 타입을 다루는 데 사용하고 있었는데, 파이썬 내장 패키지인 binascii 패키지를 대신 사용하도록 코드를 수정하였다.
시스템 라이브러리 설치 명령어도 Dockerfile 에서 제거하였다.
dockerfile
FROM python:3.12.2-alpine AS builder
WORKDIR /app
RUN pip install --no-cache-dir awscli
COPY dev_requirements.txt /app
RUN pip install --no-cache-dir --upgrade -r dev_requirements.txt
COPY ./ /app
ENTRYPOINT ["/app/scripts/run_docker.sh"]
이미지 사이즈가 1.14GB → 866MB 로 150MB 정도 작아졌다.
생각보다 shapley 패키지와 시스템 라이브러리로 많이 이미지 사이즈가 불어나지는 않았다.
불필요한 파일이 같이 올라갔나?
docker image 내에 배포와는 관련 없는 파일이 같이 말려들어갔을 수 있다.
이를 확인하기 위해 dive 를 사용하여 image 를 확인하였다.
dive
도커 이미지를 레이어별로 사이즈를 분석해준다.
도커 이미지의 파일 구조도 터미널로 보기 쉽게 볼 수 있다.
dive 실행 터미널
레이어별 사이즈, 파일 구조 를 쉽게 확인할 수 있으며 파일 사이즈를 통해 정렬하거나 필터링 기능도 제공하여 도커 이미지를 분석할 때 사용하기 매우 편리한 것 같다.
dive 툴을 통해 불필요하게 search 를 위한 파일들과 env 파일들이 들어가고 있는 것을 확인하고 .dockerignore에 추가해주었다.
이미지 사이즈는 866MB → 289MB
배포 환경에서 필요하지 않은 라이브러리 분리
이번에 테스트환경을 새롭게 구성하면서 pytest, pytest-asyncio, pytest-mock 라이브러리를 추가하였다.
테스트 환경에서 사용하고 배포시에는 분리하는 것이 이미지 사이즈를 더 줄일 수 있으므로 pyproject.toml 에서 dev-dependencies 로 분리해준다.
[tool.poetry.dependencies]
python = "^3.12"
fastapi = "^0.110.2"
uvicorn = "^0.29.0"
sqlalchemy = "^2.0.29"
...
[tool.poetry.dev-dependencies]
pytest = "^8.2.0"
pytest-asyncio = "^0.23.6"
pytest-mock = "^3.14.0"
...
dev-dependencies 를 제외한 패키지들로 배포를 적용하니 289MB → 286MB 가 되었다.
pytest 라이브러리들은 가벼운 것 같다.
파이썬 컴파일 시 불필요하게 생성하는 파일 정리
파이썬은 인터프리터 언어지만 바이트코드로 컴파일하여 .pyc 를 만들고 플랫폼 독립적으로 사용
동일한 코드를 재실행할 경우 컴파일 없이 기존 바이트코드를 사용하여 파이썬코드를 실행함
도커환경에서는 동일한 코드를 재실행할 필요가 없기 때문에 불필요한 바이트코드 파일을 생성할 필요가 없다.
Dockerfile
FROM python:3.12.2-alpine AS builder
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
WORKDIR /app
RUN pip install --no-cache-dir awscli
COPY dev_requirements.txt /app
RUN pip install --no-cache-dir --upgrade -r dev_requirements.txt
COPY ./ /app
ENTRYPOINT ["/app/scripts/run_docker.sh"]
PYTHONDONTWRITEBYTECODE
문자그대로 바이트코드를 작성하지 않고 실행하는 환경변수이다.
PYTHONUNBUFFERED
도커 이미지 최적화와는 관련없지만 파이썬 출력은 버퍼를 두어 즉시 출력하는 것이 아니라 버퍼에 어느 정도 출력이 발생하면 한번에 출력하는 방식으로 동작하는데, 로깅시에 즉시 출력해주는 것이 모니터링에 도움이 되기 때문에 버퍼를 비활성화해주는 환경변수이다.
이미지 사이즈 286MB → 276MB
불필요한 파일이 같이 들어간 것이 이미지 사이즈가 커진 큰 원인이긴 했으나, 분석하는 과정에서 dive 툴이나 파이썬 환경변수에 대해 알 수 있었다.