파이썬 Docker 컨테이너화 기초: 자동화 스크립트 이미지 빌드·배포
파이썬 자동화 스크립트를 Docker 이미지로 만드는 Dockerfile 작성법부터 빌드·실행, 볼륨과 환경 변수, 이미지 최적화와 레지스트리 배포까지 설명합니다.

파이썬 자동화 스크립트를 Docker로 배포하려면 Dockerfile과 .dockerignore를 만들고, 의존성을 먼저 복사해 설치한 뒤 소스 코드를 넣어 이미지를 빌드하면 됩니다. 비밀값과 결과 파일은 이미지에 넣지 말고 환경 변수와 볼륨으로 전달해야 같은 이미지를 개발 PC와 서버에서 안전하게 재사용할 수 있습니다.
Docker 공식 Python 컨테이너화 가이드 확인하기
핵심 요약
Dockerfile은 베이스 이미지, 작업 폴더, 의존성 설치, 소스 복사와 실행 명령을 정의합니다.requirements.txt를 소스보다 먼저 복사하면 의존성 레이어 캐시를 재사용할 수 있습니다..dockerignore로 가상환경, 캐시, Git 폴더와 비밀 설정을 빌드 대상에서 제외합니다.- 컨테이너는 삭제될 수 있으므로 결과 파일은 볼륨 또는 외부 저장소에 보관합니다.
자동화 스크립트 프로젝트 준비
예제로 데이터를 수집하는 main.py와 패키지 목록인 requirements.txt가 있다고 가정하겠습니다. 컨테이너는 PC의 가상환경을 복사하지 않고 깨끗한 베이스 이미지 안에서 패키지를 다시 설치합니다.
my-automation/
├── main.py
├── requirements.txt
├── Dockerfile
└── .dockerignore
requirements.txt에는 실제 사용하는 패키지와 검증된 버전을 기록하세요. 개발 PC의 모든 패키지를 무작정 넣으면 이미지가 커지고 충돌 가능성이 높아집니다. 먼저 별도 가상환경에서 스크립트가 정상 실행되는지 확인하면 컨테이너 문제와 코드 문제를 구분하기 쉽습니다.
파이썬용 Dockerfile 작성
Docker 공식 문서에 따르면 Dockerfile은 이미지를 만드는 명령을 기록한 문서입니다. FROM으로 기반 이미지를 정하고, WORKDIR로 작업 위치를 설정하며, COPY와 RUN으로 파일과 패키지를 준비한 뒤 CMD로 기본 실행 명령을 지정합니다.
FROM python:3.13-slim
ENV PYTHONDONTWRITEBYTECODE=1 PYTHONUNBUFFERED=1
WORKDIR /app
COPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt
COPY main.py ./
RUN useradd --create-home appuser
USER appuser
CMD ["python", "main.py"]
python:3.13-slim처럼 검증한 버전을 명시하세요. 무조건 latest를 쓰면 재빌드 시 파이썬 버전이 달라질 수 있습니다. 공식 Python 이미지를 사용하고 운영에 필요하지 않은 컴파일러와 편집기는 넣지 않는 편이 좋습니다.
Docker는 명령별 레이어를 캐시합니다. requirements를 소스보다 먼저 복사하면 패키지 목록이 그대로인 코드 변경에서 설치 레이어를 재사용할 수 있습니다. 반대로 COPY . .부터 하면 소스 한 줄만 바뀌어도 패키지 설치가 다시 실행될 수 있습니다.
.dockerignore 예시
.venv/
__pycache__/
*.pyc
.git/
.env
logs/
output/
.dockerignore는 불필요한 파일이 Docker 엔진으로 전송되거나 이미지 레이어에 들어가는 일을 줄입니다. 특히 .env, 인증 키와 백업 파일을 제외하세요. 실행에 필요한 템플릿까지 제외하지 않았는지도 확인해야 합니다.
이미지를 빌드하고 실행하는 명령
프로젝트 폴더에서 다음 명령으로 이미지를 만듭니다. 마지막 점은 현재 폴더를 빌드 컨텍스트로 사용한다는 뜻입니다.
docker build -t my-automation:1.0 .
docker image ls
docker run --rm my-automation:1.0
-t는 이미지 이름과 태그를 붙입니다. --rm은 실행이 끝난 컨테이너를 자동 삭제하지만 이미지나 외부 볼륨까지 지우지는 않습니다. 문제가 있으면 docker logs 컨테이너명으로 표준 출력을 확인하세요.
예약 실행은 운영체제 Cron이나 클라우드 스케줄러가 매번 컨테이너를 시작하게 구성하면 실행 단위가 명확합니다. 계속 살아 있는 스케줄러 컨테이너를 사용한다면 재시작 정책과 중복 실행 방지를 함께 설정해야 합니다.
결과 파일과 비밀값 관리
컨테이너 내부 파일은 컨테이너 삭제 시 함께 사라질 수 있습니다. 호스트 폴더를 연결하려면 실행할 때 볼륨을 지정합니다. Windows와 Linux는 경로 문법이 다르므로 운영체제에 맞는 절대 경로를 사용하세요.
docker run --rm \
--mount type=bind,source=/srv/output,target=/app/output \
--env-file .env \
my-automation:1.0
.env를 이미지에 COPY하지 마세요. 이미지는 레지스트리와 여러 서버에 복제될 수 있고 삭제한 파일도 이전 레이어에 남을 수 있습니다. 운영에서는 플랫폼의 비밀 관리 기능을 우선 사용하고 로그에 토큰이나 비밀번호가 출력되지 않도록 합니다.
이미지 최적화와 보안 기준
| 항목 | 권장 방법 | 이유 |
|---|---|---|
| 베이스 이미지 | 공식 이미지의 검증된 버전 | 출처와 업데이트 경로 확인 |
| 사용자 | 비루트 사용자 실행 | 권한 범위 축소 |
| 패키지 | 필요한 것만 설치 | 용량과 공격 표면 감소 |
| 빌드 대상 | .dockerignore 적용 | 속도와 비밀 보호 |
| 캐시 | 의존성을 먼저 설치 | 반복 빌드 단축 |
| 업데이트 | 정기 재빌드와 검사 | 보안 수정 반영 |
Docker 공식 권장사항은 작고 신뢰할 수 있는 베이스 이미지, 불필요한 패키지 제외, 비루트 사용자와 정기 재빌드를 강조합니다. 빌드 도구가 필요하다면 다단계 빌드로 컴파일 단계와 실행 단계를 분리해 최종 이미지에 필요한 결과물만 복사할 수 있습니다.
태그를 붙여 레지스트리에 배포
서버에서 같은 이미지를 받으려면 Docker Hub나 사설 레지스트리에 푸시합니다. 계정 또는 조직 경로를 포함해 태그한 뒤 전송합니다.
docker tag my-automation:1.0 account/my-automation:1.0
docker push account/my-automation:1.0
docker pull account/my-automation:1.0
docker run --rm account/my-automation:1.0
운영에는 추적 가능한 버전 태그를 쓰고 동일 태그를 계속 덮어쓰기보다 빌드별 버전을 구분하는 것이 롤백에 유리합니다. 비공개 코드와 데이터가 포함된 이미지는 공개 저장소로 푸시하지 말고 접근 권한을 확인하세요.
실수 방지 체크리스트
- 이미지 안에 API 키와 비밀번호를 넣지 않았는지 확인합니다.
- 가상환경과 캐시가 빌드 대상에서 제외됐는지 확인합니다.
- 파이썬과 패키지 버전을 검증했습니다.
- 비루트 사용자로 파일을 읽고 쓸 수 있는지 시험합니다.
- 결과 파일이 외부 볼륨이나 저장소에 남는지 확인합니다.
- 종료 코드가 성공과 실패를 정확히 구분하는지 확인합니다.
- 테스트한 이미지와 운영에 배포할 이미지가 같은지 확인합니다.
자주 묻는 질문
1. Docker와 가상환경은 같은 기능인가요?
아닙니다. 가상환경은 파이썬 패키지를 분리하고, 컨테이너는 파일 시스템과 실행 환경까지 함께 격리합니다.
2. Dockerfile 확장자는 무엇인가요?
기본 파일명은 확장자 없는 Dockerfile입니다. 편집기가 .txt를 붙이지 않게 주의하세요.
3. slim과 alpine 중 무엇이 좋나요?
필요한 라이브러리 호환성과 빌드 난이도를 확인해야 합니다. 일반적인 Python 패키지는 slim이 편한 경우가 많습니다.
4. COPY와 ADD 중 무엇을 쓰나요?
단순 파일 복사는 의미가 명확한 COPY를 우선 사용합니다. ADD의 추가 기능이 필요할 때만 선택하세요.
5. EXPOSE를 쓰면 포트가 자동 공개되나요?
아닙니다. 실제 호스트 연결은 실행할 때 -p 같은 설정이 필요합니다.
6. 컨테이너에서 한글 파일이 깨지면 어떻게 하나요?
파일을 UTF-8로 저장하고 Python 입출력에서 인코딩을 명시하세요. 필요한 경우 로케일도 확인합니다.
7. requirements.txt가 바뀌면 어떻게 하나요?
이미지를 다시 빌드해야 합니다. 기존 컨테이너에 직접 설치하기보다 새 이미지로 교체하세요.
8. 자동화 결과 CSV가 사라지는 이유는 무엇인가요?
컨테이너 내부에만 저장했기 때문일 수 있습니다. 바인드 마운트, 볼륨 또는 외부 저장소를 사용하세요.
9. 이미지 안에서 Cron을 실행해도 되나요?
가능하지만 프로세스 관리가 복잡해집니다. 외부 스케줄러가 컨테이너를 시작하는 방법도 비교하세요.
10. Docker 이미지를 배포하면 코드가 숨겨지나요?
아닙니다. 이미지를 받은 사용자는 레이어와 파일을 확인할 수 있으므로 코드 보호 수단이 아닙니다.
공식 출처
- Docker Docs: Writing a Dockerfile
- Docker Docs: Building best practices
- Docker Docs: Python language guide
공식 문서 확인일: 2026년 8월 30일