如何在每次不重建镜像的情况下更新源代码?

How to update source code without rebuilding image each time?

有什么方法可以避免每次更改源代码时都重建 Docker 图像?

我想我已经优化了我的 Docker 文件以减少构建时间,但它总是有 2 个命令和一些等待时间,有时只添加一行代码。它比简单的 CTRL + S 更长并检查结果。

我必须为我的代码中的每个小更新执行的命令:

docker-compose down
docker-compose build
docker-compose up

这是我的 Docker 文件:

FROM python:3-slim as development

ENV PYTHONUNBUFFERED=1

COPY ./requirements.txt /requirements.txt
COPY ./scripts /scripts

EXPOSE 80

RUN apt-get update && \
    apt-get install -y \
    bash \
    build-essential \
    gcc \
    libffi-dev \
    musl-dev \
    openssl \
    wget \
    postgresql \
    postgresql-client \
    libglib2.0-0 \
    libnss3 \
    libgconf-2-4 \
    libfontconfig1 \
    libpq-dev && \
    pip install -r /requirements.txt && \
    mkdir -p /vol/web/static && \
    chmod -R 755 /vol && \
    chmod -R +x /scripts

COPY ./files /files

WORKDIR /files

ENV PATH="/scripts:/py/bin:$PATH"

CMD ["run.sh"]

这是我的 docker-compose.yml 文件:

version: '3.9'

x-database-variables: &database-variables
  POSTGRES_DB: ${POSTGRES_DB}
  POSTGRES_USER: ${POSTGRES_USER}
  POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
  ALLOWED_HOSTS: ${ALLOWED_HOSTS}

x-app-variables: &app-variables
  <<: *database-variables
  POSTGRES_HOST: ${POSTGRES_HOST}
  SPOTIPY_CLIENT_ID: ${SPOTIPY_CLIENT_ID}
  SPOTIPY_CLIENT_SECRET: ${SPOTIPY_CLIENT_SECRET}
  SECRET_KEY: ${SECRET_KEY}
  CLUSTER_HOST: ${CLUSTER_HOST}
  DEBUG: 0

services:
  website:
    build:
      context: .
    restart: always
    volumes:
      - static-data:/vol/web
    environment: *app-variables
    depends_on:
      - postgres

  postgres:
    image: postgres
    restart: always
    environment: *database-variables
    volumes:
      - db-data:/var/lib/postgresql/data

  proxy:
    build:
      context: ./proxy
    restart: always
    depends_on:
      - website
    ports:
      - 80:80
      - 443:443
    volumes:
      - static-data:/vol/static
      - ./files/templates:/var/www/html
      - ./proxy/default.conf:/etc/nginx/conf.d/default.conf
      - ./etc/letsencrypt:/etc/letsencrypt

volumes:
  static-data:
  db-data:

通过 docker-compose.yml:

将脚本文件直接挂载到容器中
volumes:
  - ./scripts:/scripts
  - ./files:/files

请记住,如果您在 Dockerfile 中使用 WORKDIR,则必须使用前缀。

快回答

Is there a way to avoid rebuilding my Docker image each time I make a change in my source code ?

如果您的应用需要构建步骤,您不能跳过它。

同样在你的情况下,你可以在 python 应用程序之前启动需求,因此在每次修改源代码时,你只需要构建 & 运行 你的 python 应用程序,不是整个堆栈:postgress、代理等

Docker 目的

主要 docker 目标或功能是使开发人员能够 将应用程序打包 到易于部署到任何地方的容器中,从而简化您的基础架构。

因此,从这个意义上说,docker 并不是严格意义上的开发阶段。在开发阶段,程序员应该使用专门的 IDE(eclipse、intellij、visual studio 等)来创建和更新源代码。

这些 IDEs 具有热重载(源代码更改时自动更新应用程序)、变量和方法自动完成等功能。这些功能可以减少开发人员的时间。

Docker 开发人员更改源代码

不是主要目标,但如果您没有专门的 ide 或者您的开发人员工作空间非常有限,docker 可以拯救您

如果您是 java 开发人员(例如),您需要在您的机器上安装 java 和一些 IDE 像 eclipse,配置 maven 等等。随着docker,您可以创建一个包含所有必需技术的图像,并且 在您的 之间建立 一种 连接 源代码docker 容器。 docker 中的此连接称为 Volumes

对于需要构建过程的技术:java & c#,会有时间损失,因为开发人员应该对任何源代码更改执行构建。正如我所解释的那样,使用专门的 ide 不需要这样做。

我的技术案例不需要构建过程,例如:php,只需 libraries/dependencies 安装,docker 的工作方式几乎与专门的 IDE 相同。

Docker 使用热重载进行本地开发

就您而言,您的应用基于 python。 Python 不需要构建过程。只是库安装,所以如果你想用 python 开发,使用 docker 而不是经典方法:安装 python,执行 python app.py,等等你应该按照以下步骤操作:

  • 不要将源代码复制到容器中
  • 只需将 requirements.txt 传递给容器
  • 执行容器
  • 的pip install inside
  • 运行 你的应用程序 inside 容器
  • 创建一个 docker 卷:您的源代码 -> 容器上的内部文件夹

这里是一些 python 带有热重载的框架的例子:

FROM python:3
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
COPY requirements.txt /usr/src/app
RUN pip install -r requirements.txt
CMD [ "mkdocs", "serve",  "--dev-addr=0.0.0.0:8000" ]

以及如何构建为开发版本:

docker build -t myapp-dev .

以及如何 运行 它与卷 同步 您的开发人员随容器变化:

docker run --name myapp-dev -it --rm -p 8000:8000 -v $(pwd):/usr/src/app mydocs-dev

总而言之,这将是 运行 您的应用 docker 在开发阶段的流程:

  • 在应用程序之前启动需求(数据库、api 等)
  • 为开发阶段创建一个特殊的Docker文件
  • 构建 docker 图像用于开发目的
  • 运行 应用程序将源代码与容器同步 (-v)
  • 开发者修改源码
  • 如果你可以在 python 上使用某种热重载库
    • 应用程序已准备好从浏览器打开

Docker 用于没有热重载的本地开发

如果您不能使用热重载库,则需要构建并运行 随时测试您的源代码修改。在这种情况下,您应该将源代码复制到容器中,而不是像以前的方法那样与卷同步:

FROM python:3
RUN mkdir -p /usr/src/app
COPY . /usr/src/app
WORKDIR /usr/src/app
RUN pip install -r requirements.txt
RUN mkdocs build
WORKDIR /usr/src/app/site
CMD ["python", "-m", "http.server", "8000" ]

步骤应该是:

  • 在应用程序之前启动需求(数据库、api 等)
  • 为开发阶段创建一个特殊的Docker文件
  • 开发者修改源码
  • 建造
docker build -t myapp-dev.
  • 运行
docker run --name myapp-dev -it --rm -p 8000:8000 mydocs-dev