ModuleNotFoundError 이해 및 해결
ModuleNotFoundError 를 경험했으므로, 왜 발생했는지 그리고 어떻게 해결해야 하는지 알아보겠습니다.
Docker 에서 ModuleNotFoundError 가 발생하는 이유
ModuleNotFoundError 는 Docker 에서 몇 가지 일반적인 이유로 발생합니다.
- 종속성 설치 누락: Docker 이미지에 필요한 Python 패키지를 설치하지 않았습니다.
- 잘못된 PYTHONPATH: Python 인터프리터가 예상 위치에서 모듈을 찾을 수 없습니다.
- 파일 구조 문제: 애플리케이션 코드 구조가 가져오기 (import) 가 수행되는 방식과 일치하지 않습니다.
이 경우, Docker 이미지에 requests 패키지를 설치하지 않았기 때문에 오류가 발생했습니다. 로컬 개발 환경에서는 이 패키지를 전역적으로 설치했을 수 있지만, Docker 컨테이너는 격리된 환경입니다.
방법 1: Dockerfile 에서 pip 를 사용하여 종속성 설치
Dockerfile 을 수정하여 필요한 종속성을 설치해 보겠습니다.
nano Dockerfile
다음 내용으로 Dockerfile 을 업데이트합니다.
FROM python:3.9-slim
WORKDIR /app
COPY app.py .
## Fix Method 1: Directly install the required package
RUN pip install requests==2.28.1
CMD ["python", "app.py"]
이 업데이트된 이미지를 빌드하고 실행해 보겠습니다.
docker build -t python-app-fixed-1 .
패키지 설치를 포함하는 다음과 유사한 출력을 볼 수 있습니다.
Sending build context to Docker daemon 3.072kB
Step 1/5 : FROM python:3.9-slim
---> 3a4bac80b3ea
Step 2/5 : WORKDIR /app
---> Using cache
---> a8a4f574dbf5
Step 3/5 : COPY app.py .
---> Using cache
---> 7d5ae315f84b
Step 4/5 : RUN pip install requests==2.28.1
---> Running in 5a6d7e8f9b0c
Collecting requests==2.28.1
Downloading requests-2.28.1-py3-none-any.whl (62 kB)
Collecting charset-normalizer<3,>=2
Downloading charset_normalizer-2.1.1-py3-none-any.whl (39 kB)
Collecting certifi>=2017.4.17
Downloading certifi-2022.9.24-py3-none-any.whl (161 kB)
Collecting idna<4,>=2.5
Downloading idna-3.4-py3-none-any.whl (61 kB)
Collecting urllib3<1.27,>=1.21.1
Downloading urllib3-1.26.12-py2.py3-none-any.whl (140 kB)
Installing collected packages: urllib3, idna, charset-normalizer, certifi, requests
Successfully installed certifi-2022.9.24 charset-normalizer-2.1.1 idna-3.4 requests-2.28.1 urllib3-1.26.12
---> 2b3c4d5e6f7g
Removing intermediate container 5a6d7e8f9b0c
Step 5/5 : CMD ["python", "app.py"]
---> Running in 8h9i0j1k2l3m
---> 3n4o5p6q7r8s
Removing intermediate container 8h9i0j1k2l3m
Successfully built 3n4o5p6q7r8s
Successfully tagged python-app-fixed-1:latest
이제 수정된 컨테이너를 실행해 보겠습니다.
docker run python-app-fixed-1
다음과 유사한 출력을 볼 수 있습니다.
Status code: 200
Content length: 1256 characters
훌륭합니다! 필요한 종속성을 설치했으므로 애플리케이션이 이제 성공적으로 실행됩니다.
방법 2: 종속성 관리를 위해 requirements.txt 사용
패키지를 직접 설치하는 것도 작동하지만, 더 체계적인 종속성 관리를 위해 requirements.txt 파일을 사용하는 것이 더 좋은 방법입니다. Dockerfile 을 업데이트해 보겠습니다.
nano Dockerfile
다음 내용으로 Dockerfile 을 업데이트합니다.
FROM python:3.9-slim
WORKDIR /app
## Copy requirements first to leverage Docker cache
COPY requirements.txt .
## Fix Method 2: Use requirements.txt
RUN pip install -r requirements.txt
## Copy the rest of the application
COPY app.py .
CMD ["python", "app.py"]
이 접근 방식에는 몇 가지 장점이 있습니다.
- 종속성 관리를 코드와 분리합니다.
- 종속성을 쉽게 업데이트할 수 있습니다.
- Docker 이미지 레이어 캐싱 (layer caching) 에 대한 모범 사례를 따릅니다.
이 업데이트된 이미지를 빌드하고 실행해 보겠습니다.
docker build -t python-app-fixed-2 .
이전 빌드와 유사한 출력을 볼 수 있지만, 이번에는 requirements.txt 를 사용합니다.
Sending build context to Docker daemon 4.096kB
Step 1/5 : FROM python:3.9-slim
---> 3a4bac80b3ea
Step 2/5 : WORKDIR /app
---> Using cache
---> a8a4f574dbf5
Step 3/5 : COPY requirements.txt .
---> Using cache
---> b2c3d4e5f6g7
Step 4/5 : RUN pip install -r requirements.txt
---> Running in h8i9j0k1l2m3
Collecting requests==2.28.1
Using cached requests-2.28.1-py3-none-any.whl (62 kB)
Collecting charset-normalizer<3,>=2
Using cached charset_normalizer-2.1.1-py3-none-any.whl (39 kB)
Collecting idna<4,>=2.5
Using cached idna-3.4-py3-none-any.whl (61 kB)
Collecting certifi>=2017.4.17
Using cached certifi-2022.9.24-py3-none-any.whl (161 kB)
Collecting urllib3<1.27,>=1.21.1
Using cached urllib3-1.26.12-py2.py3-none-any.whl (140 kB)
Installing collected packages: urllib3, idna, charset-normalizer, certifi, requests
Successfully installed certifi-2022.9.24 charset-normalizer-2.1.1 idna-3.4 requests-2.28.1 urllib3-1.26.12
---> n4o5p6q7r8s9
Removing intermediate container h8i9j0k1l2m3
Step 5/5 : COPY app.py .
---> t0u1v2w3x4y5
Step 6/6 : CMD ["python", "app.py"]
---> Running in z5a6b7c8d9e0
---> f1g2h3i4j5k6
Removing intermediate container z5a6b7c8d9e0
Successfully built f1g2h3i4j5k6
Successfully tagged python-app-fixed-2:latest
이제 컨테이너를 실행해 보겠습니다.
docker run python-app-fixed-2
성공적인 동일한 출력을 볼 수 있습니다.
Status code: 200
Content length: 1256 characters
두 가지 다른 방법을 사용하여 ModuleNotFoundError 를 성공적으로 해결했습니다!