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.

撰写文件中的更正:

  1. 由于 docker 堆栈使用图像创建服务,因此您需要在 app 服务中指定 image: "<image name>",就像在 postgres 服务中所做的那样。正如您所提到的,build 指令图像名称是强制性的,因为 docker-compose 不知道将图像命名为什么。Reference.
  2. 如果您要在多服务器中部署应用程序,则需要注册服务器。既然你已经提到它是一个单节点部署,只要在服务器上有图像 pulled/built 就足够了。但建议使用私有注册表方法。
  3. 我的建议是不要将所有服务组合到一个 docker-compose 文件中。原因是当您 deploy/destroy 使用 docker-compose 文件时,所有服务都将被关闭。这是一种紧耦合。当然,我知道所有其他服务都依赖于 DB。在这种情况下,请确保首先启动数据库服务,然后再启动其他服务。
  4. 不要指定 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 我已经解释了理想的推荐方式。