使用Dockerfile复制代码或使用Docker-compose装载卷

pb3skfrl  于 2022-12-03  发布在  Docker
关注(0)|答案(3)|浏览(228)

我正在学习Docker website上的官方教程
Docker文件是

FROM python:3
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1
WORKDIR /code
COPY requirements.txt /code/
RUN pip install -r requirements.txt
COPY . /code/

对接合成为:

web:
    build: .
    command: python manage.py runserver 0.0.0.0:8000
    volumes:
      - .:/code

我不明白为什么他们在Dockerfile中复制代码COPY . /code/,然后又在docker-compose - .:/code中挂载它?如果我复制或挂载,这还不够吗?

shyt4zoc

shyt4zoc1#

docker-compose.yml文件中的volumes:command:都是不必要的,应该删除。要运行的代码和默认CMD应该包含在Dockerfile中。
当您设置Docker环境时,假设您被授予了对一个全新虚拟机的root访问权限,该虚拟机上除了Docker之外什么都没有安装。理想的情况是能够将docker run your-image作为单个命令从某个注册表中提取出来,并使用尽可能少的附加选项。当您运行映像时,您不需要单独提供其源代码或要运行的命令。这些通常应该被构建到映像中。
在大多数情况下,您应该能够使用相当少的选项构建Compose设置。(如果计划推送映像,则两者都有),通常为environment:ports:depends_on:(注意后一种选择的局限性),并且您的数据库容器需要volumes:作为其持久化状态。
如果你需要在同一个图像和代码库上运行一个单独的命令,那么你需要在Compose中覆盖command:。在Python上下文中,这通常会出现在Django应用程序旁边运行一个Celery worker。
下面是一个完整的例子,它是一个数据库支持的Web应用程序,有一个异步工作线程。Redis缓存层没有持久性,除了数据库存储,没有任何文件存储在本地的任何容器中。缺少的一点是数据库凭证的设置,它需要额外的environment:变量。注意代码缺少volumes:。单个command:覆盖(如果需要),environment:变量提供主机名。

version: '3.8'
services:
  app:
    build: .
    ports: ['8000:8000']
    environment:
      REDIS_HOST: redis
      PGHOST: db
  worker:
    build: .
    command: celery worker -A queue -l info
    environment:
      REDIS_HOST: redis
      PGHOST: db
  redis:
    image: redis:latest
  db:
    image: postgres:13
    volumes:
      - pgdata:/var/lib/postgresql/data
volumes:
  pgdata:

当你看到volumes:像这样覆盖图像的代码时,这通常是为了避免在代码改变时需要重新构建图像。但是,在你展示的Docker文件中,如果requirements.txt文件没有改变,那么重新构建几乎是免费的。你也几乎总是可以在Docker之外进行日常开发--对于Python来说,在虚拟环境中-并使用容器设置进行集成测试和部署,这通常比让IDE相信它所需的语言解释器在容器中更容易。
有时候Dockerfile会做一些额外的设置(改变行尾或权限,重新排列文件),而volumes:挂载会隐藏这些设置。这意味着你从来没有真正运行过在开发中内置到映像中的代码,所以如果映像设置在某些方面有错误,你不会看到它。简而言之,它重新引入了“在我的机器上工作”的问题,而这正是Docker通常试图避免的。

8ehkhllq

8ehkhllq2#

它用于保存图像后的代码。
使用COPY时,它会将其保存为图像的一部分。
而装裱则只是在显影的时候。

mnowg1ta

mnowg1ta3#

理想情况下,我们使用一个Dockerfile来创建用于生产和开发的映像,这增加了应用运行时环境的相似性,这是一件好事。
与@大卫所写的相反:使用Docker容器进行日常开发是非常方便的。您的代码在生产和开发中运行在相同的环境中。如果您在开发中使用virtualenv,您就没有利用Docker的这个非常实用的属性。环境可能会在您不知道的情况下发生变化,并且在dev继续工作的同时prod可能会中断。
那么,我们如何让一个Dockerfile生成一个可以在生产环境中运行并在开发过程中使用的映像呢?首先,我们应该讨论我们想要运行的代码。(很可能是仓库中某个特定提交的代码)但是在开发过程中我们不断地改变我们想要运行的代码,通过 checkout 不同的分支或编辑文件。那么我们如何同时满足这两个需求呢?
我们指示Dockerfile将代码目录(在您的示例.中)复制到映像中,在您的示例/code中。这将是运行的代码。这发生在生产中。但在开发中,我们可以使用卷将/code目录 * 覆盖 * 为主机上的目录。在示例中,Docker Compose文件设置了卷。然后,我们可以轻松更改dev容器中运行的代码,而无需重建映像。

另外:即使重建很快,让Python进程用新文件重新启动也要快得多。

相关问题