docker 具有组合文件单节点和本地图像的服务
docker service with compose file single node and local image
所以我需要在 单节点服务器 上使用 docker
进行滚动更新。直到现在,我一直在使用 docker-compose
但不幸的是,我无法用它实现我需要的。看了网上的,docker-swarm
好像是要走的路。
我找到了如何使用 swarm 运行 一个在单个节点上具有多个副本的应用程序:
docker service create --replicas 3 --name myapp-staging myapp_app:latest
myapp:latest
正在从我的 docker-compose.yml
:
构建
version: "3.6"
services:
postgres:
env_file:
- ".env"
image: "postgres:11.0-alpine"
volumes:
- "/var/run/postgresql:/var/run/postgresql"
app:
build: "."
working_dir: /app
depends_on:
- "postgres"
env_file:
- ".env"
command: iex -S mix phx.server
volumes:
- ".:/app"
volumes:
postgres: {}
static:
driver_opts:
device: "tmpfs"
type: "tmpfs"
不幸的是,这不起作用,因为它没有从 docker-compose.yml
文件中获取配置:.env
文件、command
条目等
更深入地搜索,我发现使用
docker stack deploy -c docker-compose.yml <name>
将使用我的 docker-compose.yml
配置创建服务。
但随后我收到以下错误消息:
failed to update service myapp-staging_postgres: Error response from daemon: rpc error: code = InvalidArgument desc = ContainerSpec: image reference must be provided
看来我必须使用注册表并将我的图像推送到那里才能正常工作。我理解在多节点架构的情况下的这种需求,但在我的情况下 我不想那样做。 (载图很重,不想自己的图public,毕竟图在这里,为什么要搬到网上?)
如何使用 docker-compose.yml
中编写的本地图像和配置来设置我的 docker service
?
我可能可以使用 docker service create
选项来管理我的方式,但是那不会使用我的 docker-compose.yml
文件,所以它不会是 DRY 的,也不会是可维护的,这对我来说很重要。
docker-compose
对开发人员来说是一个很棒的工具,遗憾的是我们必须深入研究 DevOps 工具才能实现滚动更新等常见功能。整个 swarm 架构对于我现阶段的需求来说似乎太复杂了。
而不是 docker 图片,您可以直接使用那里的 docker 文件。请检查以下示例。
version: "3.7"
services:
webapp:
build: ./dir
错误是因为 compose 无法在 Docker public 注册表中找到图像。
以上方法应该可以解决您的问题。
您不必在单节点设置中使用寄存器。您可以使用此命令从本地 docker 文件在您的节点上构建 "app" 图像 -cd 到您 docker file-
的目录
docker build . -t my-app:latest
这将在您的节点上创建一个本地 docker 图像,该图像仅对您的单个节点可见,这对您的用例是有益的,但我不建议在生产设置中这样做。
您现在可以将撰写文件编辑为:
version: "3.6"
services:
postgres:
env_file:
- ".env"
image: "postgres:11.0-alpine"
volumes:
- "/var/run/postgresql:/var/run/postgresql"
app:
image: "my-app:latest"
depends_on:
- "postgres"
env_file:
- ".env"
volumes:
- ".:/app"
volumes:
postgres: {}
static:
driver_opts:
device: "tmpfs"
type: "tmpfs"
现在您可以从该节点 运行 您的堆栈,它将使用您的本地应用程序映像并受益于映像的使用 [更新 - 回滚...等]
我确实在你的堆栈文件中有一个旁注。您对两种服务使用相同的 env 文件,请注意 swarm 将查找“.env”文件 relative/next 到“.yml”文件,因此如果这不是故意的,请修改您的 env 的位置文件。
另外请注意,此解决方案仅在单节点集群上可行,如果您扩展集群,则必须使用寄存器和寄存器不必public,你可以 deploy a private registery 在你的集群上,只有你的节点可以访问它 - 或者你可以让它 public - 你的寄存器的可访问性是你的选择。
希望这对您的问题有所帮助。
基本上你需要使用 docker 图像才能使滚动更新在 docker 群中工作。另外我想澄清一下,您可以托管一个私有注册表并使用它来代替 public 一个。
详细说明:
当您尝试滚动更新时,docker swarm 的工作原理是它会查看用于服务的图像是否发生变化,如果是,则 docker swarm 会根据更新标准集安排服务更新起来并将继续努力。
假设图像没有变化,那么会发生什么?简单地 docker 将不会应用滚动更新。从技术上讲,您可以指定 --force
标志以强制更新服务,但它只会重新部署服务。
因此创建一个本地存储库并将图像存储到其中,并在 docker-compose 文件中使用该图像名称以用于群。您可以使用 SSL、用户凭据、防火墙限制来保护 repo,这取决于您。 Refer this for more details on deploying docker registry server.
撰写文件中的更正:
- 由于 docker 堆栈使用图像创建服务,因此您需要在
app
服务中指定 image: "<image name>"
,就像在 postgres
服务中所做的那样。正如您所提到的,build
指令图像名称是强制性的,因为 docker-compose 不知道将图像命名为什么。Reference.
- 如果您要在多服务器中部署应用程序,则需要注册服务器。既然你已经提到它是一个单节点部署,只要在服务器上有图像 pulled/built 就足够了。但建议使用私有注册表方法。
- 我的建议是不要将所有服务组合到一个 docker-compose 文件中。原因是当您 deploy/destroy 使用 docker-compose 文件时,所有服务都将被关闭。这是一种紧耦合。当然,我知道所有其他服务都依赖于 DB。在这种情况下,请确保首先启动数据库服务,然后再启动其他服务。
- 不要指定 env 文件,而是将其作为 Docker 文件指令的一部分。要么复制 env 文件并在入口点获取它,要么使用 ENV 变量来定义它。
还有一个更新:
Stack只是把swarm中的服务分组。
所以你的撰写文件应该是:
version: "3.6"
services:
postgres:
env_file:
- ".env"
image: "postgres:11.0-alpine"
volumes:
- "/var/run/postgresql:/var/run/postgresql"
app:
build: "."
image: "image-name:tag" #the image built will be tagged as image-name:tag
working_dir: /app # note here I've removed .env file
depends_on:
- "postgres"
command: iex -S mix phx.server
volumes:
- ".:/app"
volumes:
postgres: {}
static:
driver_opts:
device: "tmpfs"
type: "tmpfs"
Docker文件:
from baseimage:tag
COPY .env /somelocation
# your further instructions go here
RUN ... & \
... & \
... && chmod a+x /somelocation/.env
ENTRYPOINT source /somelocation/.env && ./file-to-run
替代Docker文件:
from baseimage:tag
ENV a $a
ENV b $b
ENV c $c # here a,b,c has to be exported in the shell befire building the image.
ENTRYPOINT ./file-to-run
您可能需要 运行
docker-compose build
docker-compose push (optional needed to push the image into registry in case registry is used)]
docker stack deploy -c docker-compose.yml <stackname>
注意:
即使您可以创建上述服务 by @M.Hassan 我已经解释了理想的推荐方式。
所以我需要在 单节点服务器 上使用 docker
进行滚动更新。直到现在,我一直在使用 docker-compose
但不幸的是,我无法用它实现我需要的。看了网上的,docker-swarm
好像是要走的路。
我找到了如何使用 swarm 运行 一个在单个节点上具有多个副本的应用程序:
docker service create --replicas 3 --name myapp-staging myapp_app:latest
myapp:latest
正在从我的 docker-compose.yml
:
version: "3.6"
services:
postgres:
env_file:
- ".env"
image: "postgres:11.0-alpine"
volumes:
- "/var/run/postgresql:/var/run/postgresql"
app:
build: "."
working_dir: /app
depends_on:
- "postgres"
env_file:
- ".env"
command: iex -S mix phx.server
volumes:
- ".:/app"
volumes:
postgres: {}
static:
driver_opts:
device: "tmpfs"
type: "tmpfs"
不幸的是,这不起作用,因为它没有从 docker-compose.yml
文件中获取配置:.env
文件、command
条目等
更深入地搜索,我发现使用
docker stack deploy -c docker-compose.yml <name>
将使用我的 docker-compose.yml
配置创建服务。
但随后我收到以下错误消息:
failed to update service myapp-staging_postgres: Error response from daemon: rpc error: code = InvalidArgument desc = ContainerSpec: image reference must be provided
看来我必须使用注册表并将我的图像推送到那里才能正常工作。我理解在多节点架构的情况下的这种需求,但在我的情况下 我不想那样做。 (载图很重,不想自己的图public,毕竟图在这里,为什么要搬到网上?)
如何使用 docker-compose.yml
中编写的本地图像和配置来设置我的 docker service
?
我可能可以使用 docker service create
选项来管理我的方式,但是那不会使用我的 docker-compose.yml
文件,所以它不会是 DRY 的,也不会是可维护的,这对我来说很重要。
docker-compose
对开发人员来说是一个很棒的工具,遗憾的是我们必须深入研究 DevOps 工具才能实现滚动更新等常见功能。整个 swarm 架构对于我现阶段的需求来说似乎太复杂了。
而不是 docker 图片,您可以直接使用那里的 docker 文件。请检查以下示例。
version: "3.7"
services:
webapp:
build: ./dir
错误是因为 compose 无法在 Docker public 注册表中找到图像。 以上方法应该可以解决您的问题。
您不必在单节点设置中使用寄存器。您可以使用此命令从本地 docker 文件在您的节点上构建 "app" 图像 -cd 到您 docker file-
的目录docker build . -t my-app:latest
这将在您的节点上创建一个本地 docker 图像,该图像仅对您的单个节点可见,这对您的用例是有益的,但我不建议在生产设置中这样做。
您现在可以将撰写文件编辑为:
version: "3.6"
services:
postgres:
env_file:
- ".env"
image: "postgres:11.0-alpine"
volumes:
- "/var/run/postgresql:/var/run/postgresql"
app:
image: "my-app:latest"
depends_on:
- "postgres"
env_file:
- ".env"
volumes:
- ".:/app"
volumes:
postgres: {}
static:
driver_opts:
device: "tmpfs"
type: "tmpfs"
现在您可以从该节点 运行 您的堆栈,它将使用您的本地应用程序映像并受益于映像的使用 [更新 - 回滚...等]
我确实在你的堆栈文件中有一个旁注。您对两种服务使用相同的 env 文件,请注意 swarm 将查找“.env”文件 relative/next 到“.yml”文件,因此如果这不是故意的,请修改您的 env 的位置文件。
另外请注意,此解决方案仅在单节点集群上可行,如果您扩展集群,则必须使用寄存器和寄存器不必public,你可以 deploy a private registery 在你的集群上,只有你的节点可以访问它 - 或者你可以让它 public - 你的寄存器的可访问性是你的选择。
希望这对您的问题有所帮助。
基本上你需要使用 docker 图像才能使滚动更新在 docker 群中工作。另外我想澄清一下,您可以托管一个私有注册表并使用它来代替 public 一个。
详细说明:
当您尝试滚动更新时,docker swarm 的工作原理是它会查看用于服务的图像是否发生变化,如果是,则 docker swarm 会根据更新标准集安排服务更新起来并将继续努力。
假设图像没有变化,那么会发生什么?简单地 docker 将不会应用滚动更新。从技术上讲,您可以指定 --force
标志以强制更新服务,但它只会重新部署服务。
因此创建一个本地存储库并将图像存储到其中,并在 docker-compose 文件中使用该图像名称以用于群。您可以使用 SSL、用户凭据、防火墙限制来保护 repo,这取决于您。 Refer this for more details on deploying docker registry server.
撰写文件中的更正:
- 由于 docker 堆栈使用图像创建服务,因此您需要在
app
服务中指定image: "<image name>"
,就像在postgres
服务中所做的那样。正如您所提到的,build
指令图像名称是强制性的,因为 docker-compose 不知道将图像命名为什么。Reference. - 如果您要在多服务器中部署应用程序,则需要注册服务器。既然你已经提到它是一个单节点部署,只要在服务器上有图像 pulled/built 就足够了。但建议使用私有注册表方法。
- 我的建议是不要将所有服务组合到一个 docker-compose 文件中。原因是当您 deploy/destroy 使用 docker-compose 文件时,所有服务都将被关闭。这是一种紧耦合。当然,我知道所有其他服务都依赖于 DB。在这种情况下,请确保首先启动数据库服务,然后再启动其他服务。
- 不要指定 env 文件,而是将其作为 Docker 文件指令的一部分。要么复制 env 文件并在入口点获取它,要么使用 ENV 变量来定义它。
还有一个更新: Stack只是把swarm中的服务分组。
所以你的撰写文件应该是:
version: "3.6"
services:
postgres:
env_file:
- ".env"
image: "postgres:11.0-alpine"
volumes:
- "/var/run/postgresql:/var/run/postgresql"
app:
build: "."
image: "image-name:tag" #the image built will be tagged as image-name:tag
working_dir: /app # note here I've removed .env file
depends_on:
- "postgres"
command: iex -S mix phx.server
volumes:
- ".:/app"
volumes:
postgres: {}
static:
driver_opts:
device: "tmpfs"
type: "tmpfs"
Docker文件:
from baseimage:tag
COPY .env /somelocation
# your further instructions go here
RUN ... & \
... & \
... && chmod a+x /somelocation/.env
ENTRYPOINT source /somelocation/.env && ./file-to-run
替代Docker文件:
from baseimage:tag
ENV a $a
ENV b $b
ENV c $c # here a,b,c has to be exported in the shell befire building the image.
ENTRYPOINT ./file-to-run
您可能需要 运行
docker-compose build
docker-compose push (optional needed to push the image into registry in case registry is used)]
docker stack deploy -c docker-compose.yml <stackname>
注意:
即使您可以创建上述服务