programing

Python 프로젝트용 도커 이미지를 빌드할 때 패키지 재설치를 피하는 방법은 무엇입니까?

topblog 2023. 8. 1. 20:13
반응형

Python 프로젝트용 도커 이미지를 빌드할 때 패키지 재설치를 피하는 방법은 무엇입니까?

내 도커 파일은 다음과 같습니다.

FROM my/base

ADD . /srv
RUN pip install -r requirements.txt
RUN python setup.py install

ENTRYPOINT ["run_server"]

새 이미지를 구축할 때마다 종속성을 다시 설치해야 하는데, 이는 해당 지역에서 매우 느릴 수 있습니다.

내가 생각하는 한 가지 방법은cache는 설된패다재정합다니의음을치는키를 입니다.my/base다음과 같은 최신 이미지가 있는 이미지:

docker build -t new_image_1 .
docker tag new_image_1 my/base

다음에 이 Docker 파일로 빌드할 때 이미 일부 패키지가 설치되어 있습니다.

그러나 이 솔루션에는 두 가지 문제가 있습니다.

  1. 기본 이미지를 항상 재정의할 수 있는 것은 아닙니다.
  2. 기본 이미지는 새로운 이미지가 계층화됨에 따라 점점 더 커집니다.

그렇다면 이 문제를 해결하기 위해 어떤 더 나은 해결책을 사용할 수 있을까요?

편집:

내 컴퓨터의 도커에 대한 몇 가지 정보:

☁  test  docker version
Client version: 1.1.2
Client API version: 1.13
Go version (client): go1.2.1
Git commit (client): d84a070
Server version: 1.1.2
Server API version: 1.13
Go version (server): go1.2.1
Git commit (server): d84a070
☁  test  docker info
Containers: 0
Images: 56
Storage Driver: aufs
 Root Dir: /var/lib/docker/aufs
 Dirs: 56
Execution Driver: native-0.2
Kernel Version: 3.13.0-29-generic
WARNING: No swap limit support

다음과 같은 도커 파일을 작성해 보십시오.

FROM my/base

WORKDIR /srv
ADD ./requirements.txt /srv/requirements.txt
RUN pip install -r requirements.txt
ADD . /srv
RUN python setup.py install

ENTRYPOINT ["run_server"]

한합니다.requirements.txt 코드 이 다른코파에여상이관없부에 .변경되었는지 여부.여기 예가 있어요.


여기 간단한 것이 있습니다.Hello, World!프로그램:

$ tree
.
├── Dockerfile
├── requirements.txt
└── run.py   

0 directories, 3 file

# Dockerfile

FROM dockerfile/python
WORKDIR /srv
ADD ./requirements.txt /srv/requirements.txt
RUN pip install -r requirements.txt
ADD . /srv
CMD python /srv/run.py

# requirements.txt
pytest==2.3.4

# run.py
print("Hello, World")

도커 빌드의 출력:

Step 1 : WORKDIR /srv
---> Running in 22d725d22e10
---> 55768a00fd94
Removing intermediate container 22d725d22e10
Step 2 : ADD ./requirements.txt /srv/requirements.txt
---> 968a7c3a4483
Removing intermediate container 5f4e01f290fd
Step 3 : RUN pip install -r requirements.txt
---> Running in 08188205e92b
Downloading/unpacking pytest==2.3.4 (from -r requirements.txt (line 1))
  Running setup.py (path:/tmp/pip_build_root/pytest/setup.py) egg_info for package pytest
....
Cleaning up...
---> bf5c154b87c9
Removing intermediate container 08188205e92b
Step 4 : ADD . /srv
---> 3002a3a67e72
Removing intermediate container 83defd1851d0
Step 5 : CMD python /srv/run.py
---> Running in 11e69b887341
---> 5c0e7e3726d6
Removing intermediate container 11e69b887341
Successfully built 5c0e7e3726d6

run.py:

# run.py
print("Hello, Python")

다시 빌드해 보십시오. 아래의 출력은 다음과 같습니다.

Sending build context to Docker daemon  5.12 kB
Sending build context to Docker daemon 
Step 0 : FROM dockerfile/python
---> f86d6993fc7b
Step 1 : WORKDIR /srv
---> Using cache
---> 55768a00fd94
Step 2 : ADD ./requirements.txt /srv/requirements.txt
---> Using cache
---> 968a7c3a4483
Step 3 : RUN pip install -r requirements.txt
---> Using cache
---> bf5c154b87c9
Step 4 : ADD . /srv
---> 9cc7508034d6
Removing intermediate container 0d7cf71eb05e
Step 5 : CMD python /srv/run.py
---> Running in f25c21135010
---> 4ffab7bc66c7
Removing intermediate container f25c21135010
Successfully built 4ffab7bc66c7

위에서 볼 수 있듯이, 이번 도커는 빌드하는 동안 캐시를 사용합니다.이제 업데이트합니다.requirements.txt:

# requirements.txt

pytest==2.3.4
ipython

다음은 도커 빌드의 출력입니다.

Sending build context to Docker daemon  5.12 kB
Sending build context to Docker daemon 
Step 0 : FROM dockerfile/python
---> f86d6993fc7b
Step 1 : WORKDIR /srv
---> Using cache
---> 55768a00fd94
Step 2 : ADD ./requirements.txt /srv/requirements.txt
---> b6c19f0643b5
Removing intermediate container a4d9cb37dff0
Step 3 : RUN pip install -r requirements.txt
---> Running in 4b7a85a64c33
Downloading/unpacking pytest==2.3.4 (from -r requirements.txt (line 1))
  Running setup.py (path:/tmp/pip_build_root/pytest/setup.py) egg_info for package pytest

Downloading/unpacking ipython (from -r requirements.txt (line 2))
Downloading/unpacking py>=1.4.12 (from pytest==2.3.4->-r requirements.txt (line 1))
  Running setup.py (path:/tmp/pip_build_root/py/setup.py) egg_info for package py

Installing collected packages: pytest, ipython, py
  Running setup.py install for pytest

Installing py.test script to /usr/local/bin
Installing py.test-2.7 script to /usr/local/bin
  Running setup.py install for py

Successfully installed pytest ipython py
Cleaning up...
---> 23a1af3df8ed
Removing intermediate container 4b7a85a64c33
Step 4 : ADD . /srv
---> d8ae270eca35
Removing intermediate container 7f003ebc3179
Step 5 : CMD python /srv/run.py
---> Running in 510359cf9e12
---> e42fc9121a77
Removing intermediate container 510359cf9e12
Successfully built e42fc9121a77

도커가 pip 설치 중에 캐시를 사용하지 않은 방법에 주목합니다.작동하지 않으면 도커 버전을 확인합니다.

Client version: 1.1.2
Client API version: 1.13
Go version (client): go1.2.1
Git commit (client): d84a070
Server version: 1.1.2
Server API version: 1.13
Go version (server): go1.2.1
Git commit (server): d84a070

저는 이 질문이 이미 몇 가지 인기 있는 답을 가지고 있다는 것을 이해합니다.그러나 패키지 관리자를 위해 파일을 캐시하는 새로운 방법이 있습니다.향후 빌드킷이 더 표준화될 때 좋은 답변이 될 수 있다고 생각합니다.

Docker 18.09를 기준으로 BuildKit에 대한 실험적 지원이 있습니다.BuildKit은 외부 볼륨 마운트에 대한 실험적 지원을 포함하여 도커 파일의 일부 새로운 기능에 대한 지원을 추가합니다.RUN 수 요. 이것은 우리가 캐시를 만들 수 있게 해줍니다.$HOME/.cache/pip/.

우리는 과 같은 것을 requirements.txt예를 들어 파일:

Click==7.0
Django==2.2.3
django-appconf==1.0.3
django-compressor==2.3
django-debug-toolbar==2.0
django-filter==2.2.0
django-reversion==3.0.4
django-rq==2.1.0
pytz==2019.1
rcssmin==1.0.6
redis==3.3.4
rjsmin==1.1.0
rq==1.1.0
six==1.12.0
sqlparse==0.3.0

인 예 Python 일인파썬이예Dockerfile다음과 같이 표시될 수 있습니다.

FROM python:3.7
WORKDIR /usr/src/app
COPY requirements.txt /usr/src/app/
RUN pip install -r requirements.txt
COPY . /usr/src/app

"빌드킷"을 사용하여 빌드킷을 DOCKER_BUILDKIT환경 변수 우리는 캐시되지 않은 것을 구축할 수 있습니다.pip약 약초 65안 에단계수행합다니를수▁step다니초행합▁in.

$ export DOCKER_BUILDKIT=1
$ docker build -t test .
[+] Building 65.6s (10/10) FINISHED                                                                                                                                             
 => [internal] load .dockerignore                                                                                                                                          0.0s
 => => transferring context: 2B                                                                                                                                            0.0s
 => [internal] load build definition from Dockerfile                                                                                                                       0.0s
 => => transferring dockerfile: 120B                                                                                                                                       0.0s
 => [internal] load metadata for docker.io/library/python:3.7                                                                                                              0.5s
 => CACHED [1/4] FROM docker.io/library/python:3.7@sha256:6eaf19442c358afc24834a6b17a3728a45c129de7703d8583392a138ecbdb092                                                 0.0s
 => [internal] load build context                                                                                                                                          0.6s
 => => transferring context: 899.99kB                                                                                                                                      0.6s
 => CACHED [internal] helper image for file operations                                                                                                                     0.0s
 => [2/4] COPY requirements.txt /usr/src/app/                                                                                                                              0.5s
 => [3/4] RUN pip install -r requirements.txt                                                                                                                             61.3s
 => [4/4] COPY . /usr/src/app                                                                                                                                              1.3s
 => exporting to image                                                                                                                                                     1.2s
 => => exporting layers                                                                                                                                                    1.2s
 => => writing image sha256:d66a2720e81530029bf1c2cb98fb3aee0cffc2f4ea2aa2a0760a30fb718d7f83                                                                               0.0s
 => => naming to docker.io/library/test                                                                                                                                    0.0s

하겠습니다.RUNPython 패키지를 캐시하는 단계:

# syntax=docker/dockerfile:experimental

FROM python:3.7
WORKDIR /usr/src/app
COPY requirements.txt /usr/src/app/
RUN --mount=type=cache,target=/root/.cache/pip pip install -r requirements.txt
COPY . /usr/src/app

지금 다른 빌드를 수행합니다.그것은 같은 시간이 걸릴 것입니다.그러나 이번에는 새로운 캐시 마운트에 Python 패키지를 캐싱합니다.

$ docker build -t pythontest .
[+] Building 60.3s (14/14) FINISHED                                                                                                                                             
 => [internal] load build definition from Dockerfile                                                                                                                       0.0s
 => => transferring dockerfile: 120B                                                                                                                                       0.0s
 => [internal] load .dockerignore                                                                                                                                          0.0s
 => => transferring context: 2B                                                                                                                                            0.0s
 => resolve image config for docker.io/docker/dockerfile:experimental                                                                                                      0.5s
 => CACHED docker-image://docker.io/docker/dockerfile:experimental@sha256:9022e911101f01b2854c7a4b2c77f524b998891941da55208e71c0335e6e82c3                                 0.0s
 => [internal] load .dockerignore                                                                                                                                          0.0s
 => [internal] load build definition from Dockerfile                                                                                                                       0.0s
 => => transferring dockerfile: 120B                                                                                                                                       0.0s
 => [internal] load metadata for docker.io/library/python:3.7                                                                                                              0.5s
 => CACHED [1/4] FROM docker.io/library/python:3.7@sha256:6eaf19442c358afc24834a6b17a3728a45c129de7703d8583392a138ecbdb092                                                 0.0s
 => [internal] load build context                                                                                                                                          0.7s
 => => transferring context: 899.99kB                                                                                                                                      0.6s
 => CACHED [internal] helper image for file operations                                                                                                                     0.0s
 => [2/4] COPY requirements.txt /usr/src/app/                                                                                                                              0.6s
 => [3/4] RUN --mount=type=cache,target=/root/.cache/pip pip install -r requirements.txt                                                                                  53.3s
 => [4/4] COPY . /usr/src/app                                                                                                                                              2.6s
 => exporting to image                                                                                                                                                     1.2s
 => => exporting layers                                                                                                                                                    1.2s
 => => writing image sha256:0b035548712c1c9e1c80d4a86169c5c1f9e94437e124ea09e90aea82f45c2afc                                                                               0.0s
 => => naming to docker.io/library/test                                                                                                                                    0.0s

60초 정도요.우리의 첫 번째 빌드와 유사합니다.

약간의 변경 사항을 변경합니다.requirements.txt 두 패키지 을 새로 등) 실행합니다

$ docker build -t pythontest .
[+] Building 15.9s (14/14) FINISHED                                                                                                                                             
 => [internal] load build definition from Dockerfile                                                                                                                       0.0s
 => => transferring dockerfile: 120B                                                                                                                                       0.0s
 => [internal] load .dockerignore                                                                                                                                          0.0s
 => => transferring context: 2B                                                                                                                                            0.0s
 => resolve image config for docker.io/docker/dockerfile:experimental                                                                                                      1.1s
 => CACHED docker-image://docker.io/docker/dockerfile:experimental@sha256:9022e911101f01b2854c7a4b2c77f524b998891941da55208e71c0335e6e82c3                                 0.0s
 => [internal] load build definition from Dockerfile                                                                                                                       0.0s
 => => transferring dockerfile: 120B                                                                                                                                       0.0s
 => [internal] load .dockerignore                                                                                                                                          0.0s
 => [internal] load metadata for docker.io/library/python:3.7                                                                                                              0.5s
 => CACHED [1/4] FROM docker.io/library/python:3.7@sha256:6eaf19442c358afc24834a6b17a3728a45c129de7703d8583392a138ecbdb092                                                 0.0s
 => CACHED [internal] helper image for file operations                                                                                                                     0.0s
 => [internal] load build context                                                                                                                                          0.7s
 => => transferring context: 899.99kB                                                                                                                                      0.7s
 => [2/4] COPY requirements.txt /usr/src/app/                                                                                                                              0.6s
 => [3/4] RUN --mount=type=cache,target=/root/.cache/pip pip install -r requirements.txt                                                                                   8.8s
 => [4/4] COPY . /usr/src/app                                                                                                                                              2.1s
 => exporting to image                                                                                                                                                     1.1s
 => => exporting layers                                                                                                                                                    1.1s
 => => writing image sha256:fc84cd45482a70e8de48bfd6489e5421532c2dd02aaa3e1e49a290a3dfb9df7c                                                                               0.0s
 => => naming to docker.io/library/test                                                                                                                                    0.0s

겨우 16초!

우리는 더 이상 모든 파이썬 패키지를 다운로드하지 않기 때문에 이 속도를 높이고 있습니다.관리자에 .pip캐시 볼륨 마운트에 저장됩니다.볼륨 마운트는 실행 단계에 제공되어 다음과 같습니다.pip이미 다운로드한 패키지를 재사용할 수 있습니다.이 문제는 도커 계층 캐싱 외부에서 발생합니다.

이득은 큰 쪽이 훨씬 더 좋을 것입니다.requirements.txt.

주의:

  • 이것은 실험적인 Docker 파일 구문이므로 그렇게 취급해야 합니다.현재 생산 중인 이 제품으로 구축하고 싶지 않을 수도 있습니다.
  • BuildKit 항목은 현재 Docker Compose 또는 Docker API를 직접 사용하는 다른 도구에서 작동하지 않습니다. 1.25.0 기준으로 도커 합성에서 이 기능을 지원합니다. 자세한 내용은 도커 합성과 함께 BuildKit를 활성화하는 방법을 참조하십시오.
  • 현재 캐시를 관리할 수 있는 직접 인터페이스는 없습니다.다음 작업을 수행할 때 삭제됩니다.docker system prune -a.

이러한 기능이 빌드를 위해 도커로 전환되고 빌드킷이 기본값이 되기를 바랍니다.그런 경우에는 이 답변을 업데이트하도록 하겠습니다.

활동을 워크활최면다같하십오시이음과네트려하동소을을 가리킬 수 .pip호스트 컴퓨터의 캐시 디렉토리로 이동합니다.

호스트의 pip 캐시 디렉토리 바인딩을 컨테이너의 pip 캐시 디렉토리에 마운트하여 도커 컨테이너를 실행합니다.docker run명령은 다음과 같아야 합니다.

docker run -v $HOME/.cache/pip-docker/:/root/.cache/pip image_1

그런 에 Docker 파일의 합니다.ENTRYPOINT 진또술는또)CMD진술) 대신에RUN댓글것처럼) 이미지구축 할 수 때문에 중요합니다.RUN문이 실행됨).다음과 .

FROM my/base

ADD . /srv

ENTRYPOINT ["sh", "-c", "pip install -r requirements.txt && python setup.py install && run_server"]
pipenv install

기본적으로 재잠금을 시도합니다.이 경우 Pipfile.lock이 변경되었기 때문에 Docker 빌드의 캐시된 계층은 사용되지 않습니다.문서 참조

이에 대한 솔루션은 Pipfile.lock 버전을 사용하는 것입니다.

RUN pipenv sync

대신.

JFG 피녜이로 덕분입니다.

더 좋은 방법은 Python 사이트 패키지 디렉터리를 볼륨으로 추가하는 것입니다.

services:
    web:
        build: .
        command: python manage.py runserver 0.0.0.0:8000
        volumes:
            - .:/code
            -  /usr/local/lib/python2.7/site-packages/

이렇게 하면 전체 재구성을 수행할 필요 없이 새 라이브러리를 pip로 설치할 수 있습니다.

편집: 이 대답은 무시하세요, 위의 jkukul의 대답은 저에게 효과가 있었습니다.의도는 사이트 패키지 폴더를 캐시하는 것이었습니다.그것은 다음과 같은 것으로 보일 것입니다.

volumes:
   - .:/code
   - ./cached-packages:/usr/local/lib/python2.7/site-packages/

다운로드 폴더를 캐시하는 것이 훨씬 더 깨끗합니다.또한 휠을 캐시하므로 작업을 적절하게 수행할 수 있습니다.

언급URL : https://stackoverflow.com/questions/25305788/how-to-avoid-reinstalling-packages-when-building-docker-image-for-python-project

반응형