如何防止在代码更改时必须重建映像

2024-01-11

我开始在个人项目中使用 Docker,并意识到这将我的开发时间增加到了无法接受的程度。如果我必须为每次代码更改重建映像,我宁愿启动 LXC 实例。

我听说有一种方法可以安装它,但不确定具体如何进行。我还有一个 docker compose yaml 文件,但我认为您在 Dockerfile 中安装了卷或其他内容?目标是使代码更改不需要重建容器映像。

FROM ubuntu:18.04
EXPOSE 5000

# update apt
RUN apt-get update -y
RUN apt-get install -y --no-install-recommends build-essential gcc wget

# pip installs
FROM python:3.10

# TA-Lib
RUN wget http://prdownloads.sourceforge.net/ta-lib/ta-lib-0.4.0-src.tar.gz && \
  tar -xvzf ta-lib-0.4.0-src.tar.gz && \
  cd ta-lib/ && \
  ./configure && \
  make && \
  make install

RUN rm -R ta-lib ta-lib-0.4.0-src.tar.gz

ADD app.py /
RUN pip install --upgrade pip setuptools
RUN pip install pymysql
COPY requirements.txt /tmp/
RUN pip install --requirement /tmp/requirements.txt
RUN pip freeze >> /tmp/requirement.txt

COPY . /tmp
CMD ["python", "/tmp/app.py"]

RUN chmod +x ./tmp/start.sh
RUN ./tmp/start.sh
version: '3.8'
services: 
  db:
    image: mysql:8.0.28
    command: '--default-authentication-plugin=mysql_native_password'
    restart: always
    environment:
      - MYSQL_DATABASE=#########
      - MYSQL_ROOT_PASSWORD=####

  # client:
  #   build: client
  #   ports: [3000]
  #   restart: always

  server:
    build: server
    ports: [5000]
    restart: always

以下是我建议的加快开发速度的建议:

将挂载代码绑定到容器中

A 绑定挂载 https://docs.docker.com/storage/bind-mounts/是容器和主机之间共享的目录。这是它的语法:

version: '3.8'
services: 
  # ... other services ...

  server:
    build: server
    ports: [5000]
    restart: always
    volumes:
      # Map the server directory in into the container at /code
      - ./server:/code

安装的第一部分,./server是相对于 docker-compose.yml 文件所在的目录。如果服务器目录和 docker-compose.yml 文件位于不同的目录中,则需要更改这部分。

之后,您需要删除 Dockerfile 中将代码复制到容器中的部分。像这样的东西:

# pip installs
FROM python:3.10

# TA-Lib
RUN wget http://prdownloads.sourceforge.net/ta-lib/ta-lib-0.4.0-src.tar.gz && \
  tar -xvzf ta-lib-0.4.0-src.tar.gz && \
  cd ta-lib/ && \
  ./configure && \
  make && \
  make install

RUN rm -R ta-lib ta-lib-0.4.0-src.tar.gz

RUN pip install --upgrade pip setuptools
RUN pip install pymysql
COPY requirements.txt /tmp/
RUN pip install --requirement /tmp/requirements.txt

CMD ["python", "/code/app.py"]

这种方法的优点是,当您在编辑器中点击“保存”时,更改将立即传播到容器中,而不需要重建。

语法文档 https://docs.docker.com/compose/compose-file/compose-file-v3/#short-syntax-3

关于生产版本的注意事项:我不建议在运行生产服务器时进行绑定安装。在这种情况下,我建议将代码复制到容器中,而不是使用绑定安装。这使得升级正在运行的服务器变得更加容易。我通常编写两个 Dockerfile 和两个 docker-compose.yml 文件:一组用于生产,一组用于开发。

将代码复制到容器之前安装依赖项

Dockerfile 的一部分导致了大部分速度缓慢。就是这一部分:

ADD app.py /
# ... snip two lines ...
COPY requirements.txt /tmp/
RUN pip install --requirement /tmp/requirements.txt

这会破坏 Docker 的层缓存。 Docker 能够缓存层,并在该层中没有任何更改的情况下使用缓存。但是,如果图层发生更改,则更改后的任何图层都将被重建。这意味着改变app.py会导致pip install --requirement /tmp/requirements.txt线再次运行。

要利用缓存,您应该遵循以下规则:最不频繁更改的文件放在最前面,最频繁更改的文件放在最后。由于更改项目中的代码比更改正在使用的依赖项更频繁,这意味着您应该在安装依赖项后复制 app.py 。

Dockerfile 会像这样改变:

COPY requirements.txt /tmp/
RUN pip install --requirement /tmp/requirements.txt

# After installing dependencies
ADD app.py /

在我的项目中,我发现即使我没有使用绑定安装技巧,在不更改依赖项的情况下重建容器也需要大约一秒钟的时间。

欲了解更多信息,请参阅有关层缓存的文档 https://docs.docker.com/get-started/09_image_best/#layer-caching.

删除未使用的阶段

Dockerfile 中有两个阶段:

FROM ubuntu:18.04
# ... snip ...
FROM python:3.10

The FROM命令意味着您将丢弃图像中的所有内容并从新的基础图像开始。这意味着这两行之间的所有内容都没有真正执行任何操作。要解决此问题,请删除第二个之前的所有内容FROM陈述。

为什么要使用多阶段构建?有时,安装编译器、编译某些内容,然后将其复制到新映像中会很有用。Example https://docs.docker.com/develop/develop-images/multistage-build/#use-multi-stage-builds.

合并安装和删除步骤

如果要删除文件,应在创建该文件的同一层中执行此操作。原因是删除前一层中的文件并不能完全删除该文件:该文件仍然占用图像中的空间。像这样的工具dive https://github.com/wagoodman/dive可以向您显示存在此问题的文件。

以下是我建议更改此部分的方法:

RUN wget http://prdownloads.sourceforge.net/ta-lib/ta-lib-0.4.0-src.tar.gz && \
  tar -xvzf ta-lib-0.4.0-src.tar.gz && \
  cd ta-lib/ && \
  ./configure && \
  make && \
  make install

RUN rm -R ta-lib ta-lib-0.4.0-src.tar.gz

合并rm进入上一步:

RUN wget http://prdownloads.sourceforge.net/ta-lib/ta-lib-0.4.0-src.tar.gz && \
 tar -xvzf ta-lib-0.4.0-src.tar.gz && \
 cd ta-lib/ && \
 ./configure && \
 make && \
 make install && \
 cd .. && \
 rm -R ta-lib ta-lib-0.4.0-src.tar.gz
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何防止在代码更改时必须重建映像 的相关文章

随机推荐

  • 从 proguard 中排除软件包

    在 proguard cfg 中排除父包后 如何包含一些包 Ex keep com myapp 我希望混淆 com myapp data 您可以使用 ProGuard 风格的正则表达式作为类名 keep class com myapp da
  • Google 电子表格 - 从下拉项填充行

    我正在为我兄弟的建筑公司创建一个 Google 文档电子表格 这是为了帮助他提供潜在工作的报价 这样他就可以控制成本 我有三张表 报价 设置 产品 报价将包含实际的逐项报价 设置将包含一些静态值 例如增值税 产品包含产品的实际成本 即木材
  • 从条目具有不同长度的字典创建数据框

    假设我有一本包含 10 个键值对的字典 每个条目都包含一个numpy array 然而 该长度array对他们来说并不相同 我如何创建一个数据框每列持有不同的条目 当我尝试时 import pandas as pd import numpy
  • 如何将 Hibernate 代理转换为真实的实体对象

    冬眠期间Session 我正在加载一些对象 其中一些由于延迟加载而作为代理加载 一切都好 我不想关闭延迟加载 但后来我需要通过 RPC 将一些对象 实际上是一个对象 发送到 GWT 客户端 而这个具体对象恰好是一个代理 所以我需要把它变成一
  • 在生产模式下收到“用户'root'@'localhost'访问被拒绝(使用密码:NO)”并且没有记录错误

    我部署了 Rails 应用程序 但所有页面上都出现 500 错误 我的 Production log 没有显示任何内容 这是一个问题 但我做了一个 脚本 控制台生产 并尝试运行一个简单的查询 User find first 它抛出了这个 A
  • 2条正态曲线的交点

    虽然我认为这是一个基本问题 但我似乎无法找出如何在 R 中计算它 2 个或多个正态分布 拟合在直方图上 的交点 我需要 x 值 例如具有以下参数 d data frame mod c 1 2 mean c 14 16 sd c 0 9 0
  • 有没有办法仅针对其副作用来应用重构脚本?

    我有一个库已更改为引入工厂方法来替换构造函数 原因现在并不重要 在当前情况下主要是为了改进类型推断 假设有is一个 Eclipse 重构脚本 所以我几乎有一个很好的计算机可读的更改描述 有什么方法可以apply该脚本仅适用于项目uses那个
  • IE8 - 带有 margin-top 的容器:10px 没有边距

    编辑 这只发生在 IE8 中 在 IE7 Firefox Opera 等中工作正常 首先 这是我在 Photoshop 中制作的一张图片来演示我的问题 http richardknop com pict jpg http richardkn
  • 调整 2D numpy 数组的大小(不包括 NaN)

    我正在尝试调整给定因子的 2D numpy 数组的大小 从而在输出中获得更小的数组 该数组是从图像文件中读取的 其中一些值应该是 NaN 不是数字 来自 numpy 的 np nan 它是卫星遥感测量的结果 只是没有测量 一些像素 我为此找
  • Gnuplot 不同颜色

    我试图用不同的颜色为绘图和 gnuplot 中的拟合着色 但它不起作用 set ylabel s in m set xlabel t in s unset key set style line 1 lt 2 lc rgb red lw 3
  • 在 Flutter 应用程序中使用 Stripe 保持 PCI 合规性

    我正在将 Stripe 集成为支付网关 并且我正在考虑flutter stripe包装上写着 简化安全性 我们让您可以轻松收集信用卡号等敏感数据并保持 PCI 合规性 这意味着敏感数据将直接发送到 Stripe 而不是通过您的服务器 有关更
  • 当 char * 被类型定义并通过结构访问时,为什么编译器会看到 char * 和 printf 的转换说明符“s”不匹配?

    为什么编译器会抱怨以下 printf 中的参数类型 char 和转换说明符 s 不匹配 include
  • 将 MySQL 数据库拆分为单独的表

    嗯 我不是一个优秀的开发人员或数据库专家 但我对这些事情还是有一点了解的 我正在尝试使用 mysqldump 命令在 VPS 上转储数据库 该命令运行良好 但是 当我在下载转储后尝试在本地恢复时 出现超时错误 任何人都可以告诉我如何通过将数
  • 如何强制PHP/Apache再使用一年?

    因此 另一位员工交给了我一个旧项目 它的代码非常糟糕 几乎让我辞职了 两次 因为我没有那么多时间 这个任务给了我两周时间 所以我无法重写整个内容 我按照要求进行了修改 目前正在进行测试 问题是 代码应该改变它在其他年份的行为 这个问题的问题
  • typescript 扩展数组原型

    我只想使用一种方法来扩展 Array 原型 将字符串数组的每个项目转换为大写 这是我的第一种方法 Array prototype toUppercase gt map String toUppercase 为什么不工作 多谢 需要先声明该成
  • 无法为 Eclipse 安装 Maven 插件 [重复]

    这个问题在这里已经有答案了 我正在 Ubuntu 12 04 LTS 上开发 Eclipse 3 7 indigo 并且我正在尝试安装 Maven 插件 下列的this http eclipse org m2e download 页面 我添
  • 在“adb反向”上出现两次“错误:关闭”

    我正在尝试通过 ADB 反向转发端口 但它只返回以下神秘错误error closed 正常转发工作 会话片段 adb forward tcp 59778 tcp 59778 adb forward list 015d2109ce0c1a0f
  • bash trap 不会忽略信号

    请考虑这个 bash 脚本 bin bash trap INT echo sleep sleep 5 echo rsync rsync a usr lib var tmp 正如预期的那样 尝试使用 ctrl c 中断睡眠失败 但是rsync
  • 为什么“transform(s.begin(),s.end(),s.begin(),tolower)”不能编译成功?

    给出代码 include
  • 如何防止在代码更改时必须重建映像

    我开始在个人项目中使用 Docker 并意识到这将我的开发时间增加到了无法接受的程度 如果我必须为每次代码更改重建映像 我宁愿启动 LXC 实例 我听说有一种方法可以安装它 但不确定具体如何进行 我还有一个 docker compose y