来自 python:3.8.3-alpine 的 Docker 镜像大小 > 1GB

Dar*_*ren 8 django docker digital-ocean dockerfile docker-compose

我对 docker 还很陌生,尽管我读了很多文章、教程并观看了 YouTube 视频,但我仍然发现当 Python 的 alpine 图像只有大约 25 MB 时,我的图像大小超过 1 GB (如果我没读错的话!)。

我正在尝试找出如何使其更小(如果实际上需要的话)。

[注意:我一直在遵循教程来创建下面的内容。大部分都是有道理的..但有些感觉像巫毒]

这是我的 Dockerfile:

FROM python:3.8.3-alpine

ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1

RUN mkdir -p /home/app

RUN addgroup -S app && adduser -S app -G app

ENV HOME=/home/app
ENV APP_HOME=/home/app/web
RUN mkdir $APP_HOME
RUN mkdir $APP_HOME/staticfiles
RUN mkdir $APP_HOME/mediafiles
WORKDIR $APP_HOME

RUN pip install --upgrade pip

COPY requirements.txt .

RUN apk update \
    && apk add --virtual build-deps gcc python3-dev musl-dev \
    && apk add postgresql-dev \
    && apk add jpeg-dev zlib-dev libjpeg \
    && apk add --update --no-cache postgresql-client

RUN pip install -r requirements.txt

RUN apk del build-deps

COPY entrypoint.prod.sh $APP_HOME

COPY . $APP_HOME

RUN chown -R app:app $APP_HOME

USER app

ENTRYPOINT ["/home/app/web/entrypoint.prod.sh"]
Run Code Online (Sandbox Code Playgroud)

使用Pillowandpsycopg2-binary造成了世界的混乱和伤害。特别是以下情况:

RUN apk update \
    && apk add --virtual build-deps gcc python3-dev musl-dev \
    && apk add postgresql-dev \
    && apk add jpeg-dev zlib-dev libjpeg \
    && apk add --update --no-cache postgresql-client

RUN pip install -r requirements.txt

RUN apk del build-deps
Run Code Online (Sandbox Code Playgroud)

这原本是:

RUN apk update \
    && apk add --virtual build-deps gcc python3-dev musl-dev \
    && apk add postgresql \
    && apk add postgresql-dev \
    && apk add --update --no-cache postgresql-client \
    && pip install psycopg2-binary \
    && apk add jpeg-dev zlib-dev libjpeg \
    && pip install Pillow \
    && apk del build-deps
Run Code Online (Sandbox Code Playgroud)

我真的不知道需要多少上述内容才能使其发挥作用。我认为可能有一种方法可以减少构建。

我知道有一种方法可以构建原始图像,然后使用它来传输内容,但唯一的教程令人困惑,我正在努力在不增加更多复杂性的情况下解决这个问题。我真的希望有人可以亲自解释它。

我也不知道图像的大小是否来自文件requirements.txt。我正在使用 django,有很多要求:

要求.txt

asgiref==3.4.1
Babel==2.9.1
boto3==1.18.12
botocore==1.21.12
certifi==2021.5.30
charset-normalizer==2.0.4
crispy-bootstrap5==0.4
defusedxml==0.7.1
diff-match-patch==20200713
Django==3.2.5
django-anymail==8.4
django-compat==1.0.15
django-crispy-forms==1.12.0
django-environ==0.4.5
django-extensions==3.1.3
django-hijack==2.3.0
django-hijack-admin==2.1.10
django-import-export==2.5.0
django-money==2.0.1
django-recaptcha==2.0.6
django-social-share==2.2.1
django-storages==1.11.1
et-xmlfile==1.1.0
fontawesomefree==5.15.3
gunicorn==20.1.0
idna==3.2
jmespath==0.10.0
MarkupPy==1.14
odfpy==1.4.1
openpyxl==3.0.7
Pillow==8.3.1
psycopg2-binary==2.9.1
py-moneyed==1.2
python-dateutil==2.8.2
pytz==2021.1
PyYAML==5.4.1
requests==2.26.0
s3transfer==0.5.0
six==1.16.0
sqlparse==0.4.1
stripe==2.60.0
tablib==3.0.0
urllib3==1.26.6
xlrd==2.0.1
xlwt==1.3.0
Run Code Online (Sandbox Code Playgroud)

我的问题是,如何使图像变小。它需要更小吗?

我只是想找到将 Django 应用程序部署到 Digitalocean 的最佳方法,但有如此多的方法和教程等,这让我感到困惑。我不知道这是否会让使用 docker 变得更容易。我只使用他们的应用程序平台吗?那会提供 SSL 吗?使用docker等有什么优点?

docker-compose 文件(供参考)

version: '3.7'

services:
  web:
    build:
      context: .
      dockerfile: Dockerfile.prod
    command: gunicorn maffsguru.wsgi:application --bind 0.0.0.0:8000
    volumes:
      - static_volume:/home/app/web/staticfiles
      - media_volume:/home/app/web/mediafiles
    expose:
      - 8000
    env_file:
      - .env.docker
    depends_on:
      - db
  db:
    image: postgres:12.0-alpine
    env_file:
      - .env.docker
    volumes:
      - postgres_data:/var/lib/postgresql/data/
    ports:
      - 5432:5432
  nginx:
    build: ./nginx
    volumes:
      - static_volume:/home/app/web/staticfiles
      - media_volume:/home/app/web/mediafiles
    ports:
      - 1337:80
    depends_on:
      - web

volumes:
  postgres_data:
  static_volume:
  media_volume:
Run Code Online (Sandbox Code Playgroud)

只是说......以上所有似乎都有效......但我不知道图像的大小等是否会成为问题?

我也很困惑为什么 Nginx 似乎需要我执行http://0.0.0.0:1337来查看该网站。通过导航到http://0.0.0.0/来查看它不是重点吗

感谢您提供的任何建议或指导,并对我的问题的随机性表示歉意

The*_*ead 11

欢迎来到 Docker!这可能是一件让人费解的事情,尤其是在开始的时候,但你问的是真正有效的问题,而且都是相关的

减小尺寸

如何

Docker 自己的 Dockerfile 最佳实践页面是一个很好的起点:

https://docs.docker.com/develop/develop-images/dockerfile_best-practices/

它们清楚地解释了您的每个指令(COPYRUNENV等)如何创建额外的层,从而增加容器的大小。重要的是,它们展示了如何通过最小化不同的指令来减小图像大小。大量最小化的关键是RUN使用&&.

我在你的 Dockerfile 中注意到的另一件事是一个特定的行:

COPY . $APP_HOME
Run Code Online (Sandbox Code Playgroud)

现在,根据您构建容器的方式(具体来说,您将哪个文件夹作为上下文传递给 Docker),这将复制可用的所有内容。有可能,这将带入您的venv文件夹等(如果您有的话)。我觉得这对你来说可能是最大的肇事者了。您可以通过添加显式COPY文件或使用.dockerignore文件来缓解这种情况。

我构建了你的镜像(没有任何源代码,也没有复制entrypoint.sh),它的大小为 710MB 作为基础。检查源代码的大小并查看是否有其他内容可能是个好主意。在我重新安排一些命令以重用指令后,图像为 484MB,这要小得多!如果你遇到困难,我可以为你将其放入 Github 上的要点中并引导你完成它,但是 Docker 文档应该可以帮助你继续下去

为什么?

嗯,较大的应用程序/图像本身并不是坏事,但随着数据的增加,某些操作可能会变慢。

当我说操作时,我倾向于指从注册表中提取图像,或推送它们进行发布。传输 1GB 的时间比传输 50MB 的时间要长。

扩展容器时还需要​​考虑。虽然映像大小不一定与启动容器时将使用多少磁盘直接相关,但它肯定会增加对正在运行的计算机的要求,并限制其他较小设备上的要求

码头工人

使用 Docker 的优点是广泛的,如果不提交我的论文答辩文章,我无法在这里涵盖所有这些优点;-)

但主要归结为以下几点:

  • 许多提供商支持在 docker 中运行应用程序
  • Dockerfile 可帮助您在一致的环境中构建应用程序,这意味着您不必配置应用程序运行的每个主机,也不必担心版本冲突
  • 容器让您可以在一致(且相同)的环境中开发和运行应用程序
  • 容器通常提供非常好的网络功能。您将遇到的一个示例是在 docker compose 中,您只需通过主机名即可访问其他容器

nginx

据我所知,你已经把事情安排得很好了!我想象 nginx 正在“告诉你”(通过日志?)导航到,因为这就是它在容器中0.0.0.0绑定的内容。现在,您已转发来自 的流量。Docker 遵循 的格式,因此这意味着流量将被定向到容器端口。您可能需要根据您的 nginx 配置进行交换,但请放心,一旦一切设置完毕,您将能够在浏览器中导航到本地主机并查看您的网站1337:80host:containerlocalhost:133780

如果您需要上述任何方面的帮助,或者需要更多资源来帮助您,请告诉我。鉴于我们似乎位于同一时区,很高兴随时与您通信并引导您完成任何事情


Ita*_*ing 8

请注意,您必须安装编译器。该编译器占用大量空间。

大多数Python包都包含预编译的二进制包,那么为什么需要编译器呢?因为你用的是Alpine。PyPI 的二进制包 (==wheels) 不适用于 Alpine。

所以:

  1. 从 Alpine 基础镜像切换到例如python:3.8-slim-buster.
  2. 摆脱编译器安装和标头等,您可能不需要它们中的任何一个。
  3. 享受您新的快速构建,以及很可能更小的图像。

详细信息:https://pythonspeed.com/articles/alpine-docker-python/

另一种方法是多阶段构建,其中您的最终映像不包含不必要的编译器。这当然增加了更多的复杂性。

起点(这是 3 篇文章系列):https://pythonspeed.com/articles/smaller-python-docker-images/