代码之家  ›  专栏  ›  技术社区  ›  Mark Jones

如何减小python应用程序的多级docker构建的大小

  •  0
  • Mark Jones  · 技术社区  · 6 年前

    如何避免在此处使用/root/.cache?我不知道多级构建是如何工作的。

    # ---- Base python ----
    FROM python:2.7-alpine3.7 AS base
    # Create app directory
    WORKDIR /app
    
    # ---- Dependencies ----
    FROM base AS dependencies
    COPY requirements.txt ./
    RUN apk add --no-cache libgcc git build-base  && \
        pip install -r requirements.txt && \
        apk del git build-base binutils-libs binutils gmp isl libgomp libatomic pkgconf libgcc && \
        apk del mpfr3 mpc1 libstdc++ gcc musl-dev libc-dev g++ make fortify-headers ca-certificates libssh2 && \
        apk del libcurl expat pcre2 git && \
        pip uninstall -y mock PyMySQL coverage pytest pytest-cov pytest-xdist wheel setuptools && \
        rm -rf /usr/share/locale/* && \
        rm -rf /var/cache/debconf/*-old && \
        rm -rf /var/lib/apt/lists/* /var/lib/dpkg   && \
        rm -rf /usr/share/doc/* && \
        rm -rf /usr/share/man/?? && \
        rm -rf /usr/share/man/??_*
    
    # ---- Copy Files/Build ----
    FROM dependencies AS build
    WORKDIR /app
    COPY . /app
    COPY --from=dependencies /root/.cache /root/.cache
    WORKDIR /app
    

    也许我应该用虚拟机?

    1 回复  |  直到 6 年前
        1
  •  5
  •   Sathyajith Bhat ron tornambe    6 年前

    Docker多阶段构建通过创建多个阶段来工作,目的是最终图像将具有最少所需的组件

    在您的例子中,您使用的是初始构建阶段作为最终图像

    FROM python:2.7-alpine3.7 AS base
    ..
    FROM base AS dependencies
    ..
    FROM dependencies AS build
    

    但是,您还将删除在依赖关系阶段中安装的不需要的包,从而否定了多级映像的优势,因此您看不到任何可见的大小更改。

    因为你还没有发布 requirements.txt 文件,我假设它会安装烧瓶

    λ cat requirements.txt
    flask==1.0.2
    

    不过,考虑一下Dockerfile,删除删除包的命令

    # ---- Base python ----
    FROM python:2.7-alpine3.7 AS base
    # Create app directory
    WORKDIR /app
    
    # ---- Dependencies ----
    FROM base AS dependencies
    COPY requirements.txt ./
    RUN apk add --no-cache libgcc git build-base  && \
        pip install -r requirements.txt
    
    # ---- Copy Files/Build ----
    FROM dependencies AS build
    WORKDIR /app
    COPY . /app
    COPY --from=dependencies /root/.cache /root/.cache
    WORKDIR /app
    

    建立图像:

    docker build -t so:51678830 .
    Sending build context to Docker daemon  3.072kB
    Step 1/10 : FROM python:2.7-alpine3.7 AS base
     ---> b1d3c201a89a
    Step 2/10 : WORKDIR /app
     ---> Using cache
     ---> 675f27f73cf9
    Step 3/10 : FROM base AS dependencies
     ---> 675f27f73cf9
    Step 4/10 : COPY requirements.txt ./
     ---> Using cache
     ---> 288a87ba0ecf
    Step 5/10 : RUN apk add --no-cache libgcc git build-base  &&         pip install -r requirements.txt
     ---> Running in 6520cfe93603
    fetch http://dl-cdn.alpinelinux.org/alpine/v3.7/main/x86_64/APKINDEX.tar.gz
    fetch http://dl-cdn.alpinelinux.org/alpine/v3.7/community/x86_64/APKINDEX.tar.gz
    (1/23) Installing binutils-libs (2.30-r1)
    (2/23) Installing binutils (2.30-r1)
    (3/23) Installing gmp (6.1.2-r1)
    (4/23) Installing isl (0.18-r0)
    (5/23) Installing libgomp (6.4.0-r5)
    (6/23) Installing libatomic (6.4.0-r5)
    (7/23) Installing pkgconf (1.3.10-r0)
    (8/23) Installing libgcc (6.4.0-r5)
    (9/23) Installing mpfr3 (3.1.5-r1)
    (10/23) Installing mpc1 (1.0.3-r1)
    (11/23) Installing libstdc++ (6.4.0-r5)
    (12/23) Installing gcc (6.4.0-r5)
    (13/23) Installing musl-dev (1.1.18-r3)
    (14/23) Installing libc-dev (0.7.1-r0)
    (15/23) Installing g++ (6.4.0-r5)
    (16/23) Installing make (4.2.1-r0)
    (17/23) Installing fortify-headers (0.9-r0)
    (18/23) Installing build-base (0.5-r0)
    (19/23) Installing libssh2 (1.8.0-r2)
    (20/23) Installing libcurl (7.61.0-r0)
    (21/23) Installing expat (2.2.5-r0)
    (22/23) Installing pcre2 (10.30-r0)
    (23/23) Installing git (2.15.2-r0)
    Executing busybox-1.27.2-r11.trigger
    OK: 186 MiB in 53 packages
    Collecting flask==1.0.2 (from -r requirements.txt (line 1))
      Downloading https://files.pythonhosted.org/packages/7f/e7/08578774ed4536d3242b14dacb4696386634607af824ea997202cd0edb4b/Flask-1.0.2-py2.py3-none-any.whl (91kB)
    Collecting Werkzeug>=0.14 (from flask==1.0.2->-r requirements.txt (line 1))
      Downloading https://files.pythonhosted.org/packages/20/c4/12e3e56473e52375aa29c4764e70d1b8f3efa6682bef8d0aae04fe335243/Werkzeug-0.14.1-py2.py3-none-any.whl (322kB)
    Collecting click>=5.1 (from flask==1.0.2->-r requirements.txt (line 1))
      Downloading https://files.pythonhosted.org/packages/34/c1/8806f99713ddb993c5366c362b2f908f18269f8d792aff1abfd700775a77/click-6.7-py2.py3-none-any.whl (71kB)
    Collecting itsdangerous>=0.24 (from flask==1.0.2->-r requirements.txt (line 1))
      Downloading https://files.pythonhosted.org/packages/dc/b4/a60bcdba945c00f6d608d8975131ab3f25b22f2bcfe1dab221165194b2d4/itsdangerous-0.24.tar.gz (46kB)
    Collecting Jinja2>=2.10 (from flask==1.0.2->-r requirements.txt (line 1))
      Downloading https://files.pythonhosted.org/packages/7f/ff/ae64bacdfc95f27a016a7bed8e8686763ba4d277a78ca76f32659220a731/Jinja2-2.10-py2.py3-none-any.whl (126kB)
    Collecting MarkupSafe>=0.23 (from Jinja2>=2.10->flask==1.0.2->-r requirements.txt (line 1))
      Downloading https://files.pythonhosted.org/packages/4d/de/32d741db316d8fdb7680822dd37001ef7a448255de9699ab4bfcbdf4172b/MarkupSafe-1.0.tar.gz
    Building wheels for collected packages: itsdangerous, MarkupSafe
      Running setup.py bdist_wheel for itsdangerous: started
      Running setup.py bdist_wheel for itsdangerous: finished with status 'done'
      Stored in directory: /root/.cache/pip/wheels/2c/4a/61/5599631c1554768c6290b08c02c72d7317910374ca602ff1e5
      Running setup.py bdist_wheel for MarkupSafe: started
      Running setup.py bdist_wheel for MarkupSafe: finished with status 'done'
      Stored in directory: /root/.cache/pip/wheels/33/56/20/ebe49a5c612fffe1c5a632146b16596f9e64676768661e4e46
    Successfully built itsdangerous MarkupSafe
    Installing collected packages: Werkzeug, click, itsdangerous, MarkupSafe, Jinja2, flask
    Successfully installed Jinja2-2.10 MarkupSafe-1.0 Werkzeug-0.14.1 click-6.7 flask-1.0.2 itsdangerous-0.24
    Removing intermediate container 6520cfe93603
     ---> 6d73b486a703
    Step 6/10 : FROM dependencies AS build
     ---> 6d73b486a703
    Step 7/10 : WORKDIR /app
     ---> Running in 0ed8fa7f13e7
    Removing intermediate container 0ed8fa7f13e7
     ---> e61cf72b31ae
    Step 8/10 : COPY . /app
     ---> f6c7a4d3d8df
    Step 9/10 : COPY --from=dependencies /root/.cache /root/.cache
     ---> 2c15e7080c91
    Step 10/10 : WORKDIR /app
     ---> Running in 717bd7cf7b1d
    Removing intermediate container 717bd7cf7b1d
     ---> cfe7ee0c5880
    Successfully built cfe7ee0c5880
    Successfully tagged so:51678830
    

    检查图像的大小:

    docker images
    
    | REPOSITORY                    TAG                 IMAGE ID            CREATED              SIZE  |
    |--------------------------------------------------------------------------------------------------|
    | so                            51678830            4477dac77289        About a minute ago   234MB |
    

    让我们修改Dockerfile,使其使用“base”作为最终图像,但从依赖项复制缓存的pip轮

    # ---- Base python ----
    FROM python:2.7-alpine3.7 AS base
    # Create app directory
    WORKDIR /app
    
    # ---- Dependencies ----
    FROM base AS dependencies
    COPY requirements.txt ./
    RUN apk add --no-cache libgcc git build-base  && \
        pip install -r requirements.txt
    
    # ---- Copy Files/Build ----
    FROM base
    WORKDIR /app
    COPY . /app
    COPY --from=dependencies /root/.cache /root/.cache
    WORKDIR /app
    

    建立形象

    docker build -t so:51678830 .
    Sending build context to Docker daemon  3.072kB
    Step 1/10 : FROM python:2.7-alpine3.7 AS base
     ---> b1d3c201a89a
    Step 2/10 : WORKDIR /app
     ---> Running in aca871ed01e3
    Removing intermediate container aca871ed01e3
     ---> 89d357832427
    Step 3/10 : FROM base AS dependencies
     ---> 89d357832427
    Step 4/10 : COPY requirements.txt ./
     ---> 6ecbfe862e27
    Step 5/10 : RUN apk add --no-cache libgcc git build-base  &&         pip install -r requirements.txt
     ---> Running in 465256e75563
    fetch http://dl-cdn.alpinelinux.org/alpine/v3.7/main/x86_64/APKINDEX.tar.gz
    fetch http://dl-cdn.alpinelinux.org/alpine/v3.7/community/x86_64/APKINDEX.tar.gz
    (1/23) Installing binutils-libs (2.30-r1)
    (2/23) Installing binutils (2.30-r1)
    (3/23) Installing gmp (6.1.2-r1)
    (4/23) Installing isl (0.18-r0)
    (5/23) Installing libgomp (6.4.0-r5)
    (6/23) Installing libatomic (6.4.0-r5)
    (7/23) Installing pkgconf (1.3.10-r0)
    (8/23) Installing libgcc (6.4.0-r5)
    (9/23) Installing mpfr3 (3.1.5-r1)
    (10/23) Installing mpc1 (1.0.3-r1)
    (11/23) Installing libstdc++ (6.4.0-r5)
    (12/23) Installing gcc (6.4.0-r5)
    (13/23) Installing musl-dev (1.1.18-r3)
    (14/23) Installing libc-dev (0.7.1-r0)
    (15/23) Installing g++ (6.4.0-r5)
    (16/23) Installing make (4.2.1-r0)
    (17/23) Installing fortify-headers (0.9-r0)
    (18/23) Installing build-base (0.5-r0)
    (19/23) Installing libssh2 (1.8.0-r2)
    (20/23) Installing libcurl (7.61.0-r0)
    (21/23) Installing expat (2.2.5-r0)
    (22/23) Installing pcre2 (10.30-r0)
    (23/23) Installing git (2.15.2-r0)
    Executing busybox-1.27.2-r11.trigger
    OK: 186 MiB in 53 packages
    Collecting flask==1.0.2 (from -r requirements.txt (line 1))
      Downloading https://files.pythonhosted.org/packages/7f/e7/08578774ed4536d3242b14dacb4696386634607af824ea997202cd0edb4b/Flask-1.0.2-py2.py3-none-any.whl (91kB)
    Collecting Werkzeug>=0.14 (from flask==1.0.2->-r requirements.txt (line 1))
      Downloading https://files.pythonhosted.org/packages/20/c4/12e3e56473e52375aa29c4764e70d1b8f3efa6682bef8d0aae04fe335243/Werkzeug-0.14.1-py2.py3-none-any.whl (322kB)
    Collecting click>=5.1 (from flask==1.0.2->-r requirements.txt (line 1))
      Downloading https://files.pythonhosted.org/packages/34/c1/8806f99713ddb993c5366c362b2f908f18269f8d792aff1abfd700775a77/click-6.7-py2.py3-none-any.whl (71kB)
    Collecting itsdangerous>=0.24 (from flask==1.0.2->-r requirements.txt (line 1))
      Downloading https://files.pythonhosted.org/packages/dc/b4/a60bcdba945c00f6d608d8975131ab3f25b22f2bcfe1dab221165194b2d4/itsdangerous-0.24.tar.gz (46kB)
    Collecting Jinja2>=2.10 (from flask==1.0.2->-r requirements.txt (line 1))
      Downloading https://files.pythonhosted.org/packages/7f/ff/ae64bacdfc95f27a016a7bed8e8686763ba4d277a78ca76f32659220a731/Jinja2-2.10-py2.py3-none-any.whl (126kB)
    Collecting MarkupSafe>=0.23 (from Jinja2>=2.10->flask==1.0.2->-r requirements.txt (line 1))
      Downloading https://files.pythonhosted.org/packages/4d/de/32d741db316d8fdb7680822dd37001ef7a448255de9699ab4bfcbdf4172b/MarkupSafe-1.0.tar.gz
    Building wheels for collected packages: itsdangerous, MarkupSafe
      Running setup.py bdist_wheel for itsdangerous: started
      Running setup.py bdist_wheel for itsdangerous: finished with status 'done'
      Stored in directory: /root/.cache/pip/wheels/2c/4a/61/5599631c1554768c6290b08c02c72d7317910374ca602ff1e5
      Running setup.py bdist_wheel for MarkupSafe: started
      Running setup.py bdist_wheel for MarkupSafe: finished with status 'done'
      Stored in directory: /root/.cache/pip/wheels/33/56/20/ebe49a5c612fffe1c5a632146b16596f9e64676768661e4e46
    Successfully built itsdangerous MarkupSafe
    Installing collected packages: Werkzeug, click, itsdangerous, MarkupSafe, Jinja2, flask
    Successfully installed Jinja2-2.10 MarkupSafe-1.0 Werkzeug-0.14.1 click-6.7 flask-1.0.2 itsdangerous-0.24
    Removing intermediate container 465256e75563
     ---> d9a23965de75
    Step 6/10 : FROM base
     ---> 89d357832427
    Step 7/10 : WORKDIR /app
     ---> Running in bb975f43890d
    Removing intermediate container bb975f43890d
     ---> ba0d78774039
    Step 8/10 : COPY . /app
     ---> 3510860b3538
    Step 9/10 : COPY --from=dependencies /root/.cache /root/.cache
     ---> 812c65bd156b
    Step 10/10 : WORKDIR /app
     ---> Running in 4191ef84468e
    Removing intermediate container 4191ef84468e
     ---> 236d8ee0bea4
    Successfully built 236d8ee0bea4
    Successfully tagged so:51678830
    

    这样,我们得到的图像大小为60.5MB

    docker图像

    | REPOSITORY                    TAG                 IMAGE ID            CREATED              SIZE   |
    |---------------------------------------------------------------------------------------------------|
    | so                            51678830            e53282dc4fc7        2 seconds ago        60.5MB |
    

    但是,我们只复制了最终映像上的缓存文件,我们仍然需要安装它,然后 /root/.cache 可以移除。Dockerfile现在看起来像:

    # ---- Base python ----
    FROM python:2.7-alpine3.7 AS base
    # Create app directory
    WORKDIR /app
    
    # ---- Dependencies ----
    FROM base AS dependencies
    COPY requirements.txt ./
    RUN apk add --no-cache libgcc git build-base  && \
        pip install -r requirements.txt
    
    # ---- Copy Files/Build ----
    FROM base
    WORKDIR /app
    COPY . /app
    COPY --from=dependencies /root/.cache /root/.cache
    COPY requirements.txt ./
    RUN pip install -r requirements.txt && rm -rf /root/.cache
    

    塑造形象:

    docker build -t so:51678830 .
    
    
    Sending build context to Docker daemon  3.584kB
    Step 1/11 : FROM python:2.7-alpine3.7 AS base
     ---> b1d3c201a89a
    Step 2/11 : WORKDIR /app
     ---> Running in 8471e5fe8fac
    Removing intermediate container 8471e5fe8fac
     ---> 646de3787bbc
    Step 3/11 : FROM base AS dependencies
     ---> 646de3787bbc
    Step 4/11 : COPY requirements.txt ./
     ---> 4b6c6690ddf7
    Step 5/11 : RUN apk add --no-cache libgcc git build-base  &&         pip install -r requirements.txt
     ---> Running in aaa83a183ead
    fetch http://dl-cdn.alpinelinux.org/alpine/v3.7/main/x86_64/APKINDEX.tar.gz
    fetch http://dl-cdn.alpinelinux.org/alpine/v3.7/community/x86_64/APKINDEX.tar.gz
    (1/23) Installing binutils-libs (2.30-r1)
    (2/23) Installing binutils (2.30-r1)
    (3/23) Installing gmp (6.1.2-r1)
    (4/23) Installing isl (0.18-r0)
    (5/23) Installing libgomp (6.4.0-r5)
    (6/23) Installing libatomic (6.4.0-r5)
    (7/23) Installing pkgconf (1.3.10-r0)
    (8/23) Installing libgcc (6.4.0-r5)
    (9/23) Installing mpfr3 (3.1.5-r1)
    (10/23) Installing mpc1 (1.0.3-r1)
    (11/23) Installing libstdc++ (6.4.0-r5)
    (12/23) Installing gcc (6.4.0-r5)
    (13/23) Installing musl-dev (1.1.18-r3)
    (14/23) Installing libc-dev (0.7.1-r0)
    (15/23) Installing g++ (6.4.0-r5)
    (16/23) Installing make (4.2.1-r0)
    (17/23) Installing fortify-headers (0.9-r0)
    (18/23) Installing build-base (0.5-r0)
    (19/23) Installing libssh2 (1.8.0-r2)
    (20/23) Installing libcurl (7.61.0-r0)
    (21/23) Installing expat (2.2.5-r0)
    (22/23) Installing pcre2 (10.30-r0)
    (23/23) Installing git (2.15.2-r0)
    Executing busybox-1.27.2-r11.trigger
    OK: 186 MiB in 53 packages
    Collecting flask==1.0.2 (from -r requirements.txt (line 1))
      Downloading https://files.pythonhosted.org/packages/7f/e7/08578774ed4536d3242b14dacb4696386634607af824ea997202cd0edb4b/Flask-1.0.2-py2.py3-none-any.whl (91kB)
    Collecting Werkzeug>=0.14 (from flask==1.0.2->-r requirements.txt (line 1))
      Downloading https://files.pythonhosted.org/packages/20/c4/12e3e56473e52375aa29c4764e70d1b8f3efa6682bef8d0aae04fe335243/Werkzeug-0.14.1-py2.py3-none-any.whl (322kB)
    Collecting click>=5.1 (from flask==1.0.2->-r requirements.txt (line 1))
      Downloading https://files.pythonhosted.org/packages/34/c1/8806f99713ddb993c5366c362b2f908f18269f8d792aff1abfd700775a77/click-6.7-py2.py3-none-any.whl (71kB)
    Collecting itsdangerous>=0.24 (from flask==1.0.2->-r requirements.txt (line 1))
      Downloading https://files.pythonhosted.org/packages/dc/b4/a60bcdba945c00f6d608d8975131ab3f25b22f2bcfe1dab221165194b2d4/itsdangerous-0.24.tar.gz (46kB)
    Collecting Jinja2>=2.10 (from flask==1.0.2->-r requirements.txt (line 1))
      Downloading https://files.pythonhosted.org/packages/7f/ff/ae64bacdfc95f27a016a7bed8e8686763ba4d277a78ca76f32659220a731/Jinja2-2.10-py2.py3-none-any.whl (126kB)
    Collecting MarkupSafe>=0.23 (from Jinja2>=2.10->flask==1.0.2->-r requirements.txt (line 1))
      Downloading https://files.pythonhosted.org/packages/4d/de/32d741db316d8fdb7680822dd37001ef7a448255de9699ab4bfcbdf4172b/MarkupSafe-1.0.tar.gz
    Building wheels for collected packages: itsdangerous, MarkupSafe
      Running setup.py bdist_wheel for itsdangerous: started
      Running setup.py bdist_wheel for itsdangerous: finished with status 'done'
      Stored in directory: /root/.cache/pip/wheels/2c/4a/61/5599631c1554768c6290b08c02c72d7317910374ca602ff1e5
      Running setup.py bdist_wheel for MarkupSafe: started
      Running setup.py bdist_wheel for MarkupSafe: finished with status 'done'
      Stored in directory: /root/.cache/pip/wheels/33/56/20/ebe49a5c612fffe1c5a632146b16596f9e64676768661e4e46
    Successfully built itsdangerous MarkupSafe
    Installing collected packages: Werkzeug, click, itsdangerous, MarkupSafe, Jinja2, flask
    Successfully installed Jinja2-2.10 MarkupSafe-1.0 Werkzeug-0.14.1 click-6.7 flask-1.0.2 itsdangerous-0.24
    Removing intermediate container aaa83a183ead
     ---> eca67b911ca4
    Step 6/11 : FROM base
     ---> 646de3787bbc
    Step 7/11 : WORKDIR /app
     ---> Running in 0b81da90cc35
    Removing intermediate container 0b81da90cc35
     ---> 17489d37a114
    Step 8/11 : COPY . /app
     ---> 1f12ed2b9456
    Step 9/11 : COPY --from=dependencies /root/.cache /root/.cache
     ---> 850bd5d693e3
    Step 10/11 : COPY requirements.txt ./
     ---> b508d7762e8e
    Step 11/11 : RUN pip install -r requirements.txt && rm -rf /root/.cache
     ---> Running in 125afe6f16b0
    Collecting flask==1.0.2 (from -r requirements.txt (line 1))
      Using cached https://files.pythonhosted.org/packages/7f/e7/08578774ed4536d3242b14dacb4696386634607af824ea997202cd0edb4b/Flask-1.0.2-py2.py3-none-any.whl
    Collecting Werkzeug>=0.14 (from flask==1.0.2->-r requirements.txt (line 1))
      Using cached https://files.pythonhosted.org/packages/20/c4/12e3e56473e52375aa29c4764e70d1b8f3efa6682bef8d0aae04fe335243/Werkzeug-0.14.1-py2.py3-none-any.whl
    Collecting click>=5.1 (from flask==1.0.2->-r requirements.txt (line 1))
      Using cached https://files.pythonhosted.org/packages/34/c1/8806f99713ddb993c5366c362b2f908f18269f8d792aff1abfd700775a77/click-6.7-py2.py3-none-any.whl
    Collecting itsdangerous>=0.24 (from flask==1.0.2->-r requirements.txt (line 1))
    Collecting Jinja2>=2.10 (from flask==1.0.2->-r requirements.txt (line 1))
      Using cached https://files.pythonhosted.org/packages/7f/ff/ae64bacdfc95f27a016a7bed8e8686763ba4d277a78ca76f32659220a731/Jinja2-2.10-py2.py3-none-any.whl
    Collecting MarkupSafe>=0.23 (from Jinja2>=2.10->flask==1.0.2->-r requirements.txt (line 1))
    Installing collected packages: Werkzeug, click, itsdangerous, MarkupSafe, Jinja2, flask
    Successfully installed Jinja2-2.10 MarkupSafe-1.0 Werkzeug-0.14.1 click-6.7 flask-1.0.2 itsdangerous-0.24
    Removing intermediate container 125afe6f16b0
     ---> d122f42fcb72
    Successfully built d122f42fcb72
    Successfully tagged so:51678830
    

    最终生成70MB的图像

    | REPOSITORY                    TAG                 IMAGE ID            CREATED             SIZE   |
    |--------------------------------------------------------------------------------------------------|
    | so                            51678830            d122f42fcb72        4 seconds ago       69.6MB |
    

    希望一切都清楚