Docker 使源代码可用于生产中的多个容器和安装以进行开发
Docker making source code available to multiple containers in Production and mounting for development
我阅读了有关如何使源代码可供开发和生产中的 docker 容器使用的多种资源。
对我来说,它仍然不是很清楚,何时以及如何使用什么。正如我所阅读的关于如何执行此操作的不同意见。
我的目标是:
在开发中我想使用绑定挂载直接看到容器中反映的源代码变化。对于生产,我希望源代码是不可变的。
我读到我可以为此使用 docker 卷。 (我读到我不应该将源代码复制或添加到容器中以保持图像较小)但对我来说,卷和绑定安装似乎几乎相等。
源代码目录必须可以被两个不同的容器访问。其中之一确实不时写入缓存目录。
问题:
这是正确的方法吗? (在开发时绑定安装,在 PROD 中绑定卷?)
我怎样才能拥有一个 docker-compose,它根据环境制作绑定安装或卷?
我怎样才能拥有构建代码的分阶段构建,将其放入一个卷中,然后供两个容器使用?
这取决于您使用的编程语言。
对于真正的解释型语言,每次都会对代码求值。在那种情况下,您可以使用 Volume-mapping.
但是真正解释的语言并不多。
像 Python 这样的语言正在编译成 *.pyc 文件,因此不建议使用卷映射。
如果你想尝试 volume-mapping *.pyc 文件,继续吧,享受一大堆奇怪的效果:-)
我的建议是使用代码构建容器。如果您想要快速 watch-functions 开发,请尝试 运行 开发容器外的应用程序,并且仅将容器用于阶段和生产。 (如果您的应用程序甚至可以做到这一点)
您应该将应用程序代码保留在图像中(假设它是一种解释性语言)。
特别是,Docker 命名卷尤其难以管理。您将得到一个部署序列,其中包括启动一个临时容器以访问该卷,然后将数据复制到其中,然后重新启动您的容器,并且您将失去很多 Docker 的功能部署失败时回滚容器的示例。您甚至没有在此处保存任何 space,因为代码仍然存在于卷中的目标系统上。
相反,运行 同一个图像中的两个容器非常容易,您不必为此做任何特殊的事情。
# docker-compose.yml
version: '3.8'
services:
first:
image: registry.example.com/application:${APPLICATION_TAG:-latest}
ports:
- '8080:8080'
second:
image: registry.example.com/application:${APPLICATION_TAG:-latest}
environment:
FIRST_URL: 'http://first:8080/'
# no volumes: on either container
特别是对于生产用途,我添加了图像标签作为环境变量参考,因此您可以 运行
APPLICATION_TAG=20220502 docker-compose up -d
curl http://localhost:8080
...
# nope, it's not working, roll back
APPLICATION_TAG=20220429 docker-compose up -d
如果您想用完全不同的东西替换应用程序代码,也许是开发人员在他们的系统上拥有的东西,您可以添加一个 docker-compose.override.yml
文件,Compose 将 merge their settings.
# docker-compose.override.yml
version: '3.8'
services:
first:
build: .
volumes:
- .:/app
second:
build: .
volumes:
- .:/app
# no ports:, environment:, etc. on either container
您可能还会发现在开发过程中忽略 Docker 并使用普通主机工具更容易。 bind-mount 方法存在许多潜在问题:如果 Docker 文件进行了任何处理,这将不会出现在 bind-mounted 内容中,尤其是在 Node 中bind mount 还隐藏了应用程序的库树(有一个流行的 hack 将 node_modules
目录存储在匿名卷中)。绑定安装可以重新引入“在我的系统上工作”的问题,我在 SO 上看到了几个这样的例子。
我阅读了有关如何使源代码可供开发和生产中的 docker 容器使用的多种资源。
对我来说,它仍然不是很清楚,何时以及如何使用什么。正如我所阅读的关于如何执行此操作的不同意见。
我的目标是:
在开发中我想使用绑定挂载直接看到容器中反映的源代码变化。对于生产,我希望源代码是不可变的。
我读到我可以为此使用 docker 卷。 (我读到我不应该将源代码复制或添加到容器中以保持图像较小)但对我来说,卷和绑定安装似乎几乎相等。
源代码目录必须可以被两个不同的容器访问。其中之一确实不时写入缓存目录。
问题:
这是正确的方法吗? (在开发时绑定安装,在 PROD 中绑定卷?)
我怎样才能拥有一个 docker-compose,它根据环境制作绑定安装或卷?
我怎样才能拥有构建代码的分阶段构建,将其放入一个卷中,然后供两个容器使用?
这取决于您使用的编程语言。
对于真正的解释型语言,每次都会对代码求值。在那种情况下,您可以使用 Volume-mapping.
但是真正解释的语言并不多。
像 Python 这样的语言正在编译成 *.pyc 文件,因此不建议使用卷映射。
如果你想尝试 volume-mapping *.pyc 文件,继续吧,享受一大堆奇怪的效果:-)
我的建议是使用代码构建容器。如果您想要快速 watch-functions 开发,请尝试 运行 开发容器外的应用程序,并且仅将容器用于阶段和生产。 (如果您的应用程序甚至可以做到这一点)
您应该将应用程序代码保留在图像中(假设它是一种解释性语言)。
特别是,Docker 命名卷尤其难以管理。您将得到一个部署序列,其中包括启动一个临时容器以访问该卷,然后将数据复制到其中,然后重新启动您的容器,并且您将失去很多 Docker 的功能部署失败时回滚容器的示例。您甚至没有在此处保存任何 space,因为代码仍然存在于卷中的目标系统上。
相反,运行 同一个图像中的两个容器非常容易,您不必为此做任何特殊的事情。
# docker-compose.yml
version: '3.8'
services:
first:
image: registry.example.com/application:${APPLICATION_TAG:-latest}
ports:
- '8080:8080'
second:
image: registry.example.com/application:${APPLICATION_TAG:-latest}
environment:
FIRST_URL: 'http://first:8080/'
# no volumes: on either container
特别是对于生产用途,我添加了图像标签作为环境变量参考,因此您可以 运行
APPLICATION_TAG=20220502 docker-compose up -d
curl http://localhost:8080
...
# nope, it's not working, roll back
APPLICATION_TAG=20220429 docker-compose up -d
如果您想用完全不同的东西替换应用程序代码,也许是开发人员在他们的系统上拥有的东西,您可以添加一个 docker-compose.override.yml
文件,Compose 将 merge their settings.
# docker-compose.override.yml
version: '3.8'
services:
first:
build: .
volumes:
- .:/app
second:
build: .
volumes:
- .:/app
# no ports:, environment:, etc. on either container
您可能还会发现在开发过程中忽略 Docker 并使用普通主机工具更容易。 bind-mount 方法存在许多潜在问题:如果 Docker 文件进行了任何处理,这将不会出现在 bind-mounted 内容中,尤其是在 Node 中bind mount 还隐藏了应用程序的库树(有一个流行的 hack 将 node_modules
目录存储在匿名卷中)。绑定安装可以重新引入“在我的系统上工作”的问题,我在 SO 上看到了几个这样的例子。