4

所以我需要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将使用我的配置创建服务。

但随后我收到以下错误消息:

未能更新服务 myapp-staging_postgres:来自守护程序的错误响应:rpc 错误:代码 = InvalidArgument desc = ContainerSpec:必须提供图像参考

所以看来我必须使用注册表并将我的图像推送到那里才能正常工作。在多节点架构的情况下,我理解这种需求,但就我而言,我不想这样做。(携带图片很重,我不希望我的图片被公开,毕竟图片就在这儿,为什么要把它搬到网上呢?)

如何设置我docker service使用的本地图像和写入的配置docker-compose.yml

我可能可以使用docker service create选项来管理我的方式,但这不会使用我的docker-compose.yml文件,因此它不会是 DRY 也不是可维护的,这对我来说很重要。

docker-compose对开发人员来说是一个很棒的工具,很遗憾我们不得不深入研究 DevOps 工具来实现滚动更新等常见功能。在这个阶段,对于我的需求来说,整个 swarm 架构似乎太复杂了。

4

3 回答 3

3

不必在单节点设置中使用注册表。您可以使用此命令从本地 docker 文件在您的节点上构建您的“应用程序”映像 -cd 到您的 docker 文件的目录 -

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 将查找“.yml”文件相对/旁边的“.env”文件,因此如果这不是故意的,请修改您的 env 文件的位置。

另外请注意,此解决方案仅在单节点集群上可行,如果您扩展集群,则必须使用注册表,并且注册表不必是 公共的,您可以在集群上部署私有注册表,并且只有您的节点可以访问它-或者您可以将其公开-您的注册表的可访问性是您的选择。

希望这对您的问题有所帮助。

于 2019-09-16T10:14:56.670 回答
0

您可以直接使用那里的 docker 文件,而不是 docker 图像。请检查以下示例。

version: "3.7"
services:
  webapp:
    build: ./dir

该错误是因为 compose 无法在 Docker 公共注册表上找到图像。以上方法应该可以解决您的问题。

于 2019-09-12T11:17:10.763 回答
0

基本上,您需要使用 docker 图像才能使滚动更新在 docker swarm 中工作。另外我想澄清一下,您可以托管一个私有注册表并使用它而不是公共注册表。

详细说明:当您尝试滚动更新时,docker swarm 的工作原理是,它会查看用于服务的图像是否发生变化,如果是,那么 docker swarm 会根据更新标准的设置安排服务更新并将继续工作它。假设图像没有变化,那么会发生什么?只是 docker 不会应用滚动更新。从技术上讲,您可以指定--force标志以使其强制更新服务,但它只会重新部署服务。

因此,创建一个本地 repo 并将图像存储到其中,并在 docker-compose 文件中使用该图像名称以用于 swarm。您可以使用 SSL、用户凭据、防火墙限制来保护存储库,这取决于您。有关部署 docker 注册表服务器的更多详细信息,请参阅此内容。

撰写文件中的更正:

  1. 由于 docker stack 使用图像来创建服务,因此您需要在服务中指定image: "<image name>"app就像在postgres服务中完成一样。正如您提到build的指令 image-name 是强制性的,因为 docker-compose 不知道将图像命名为什么。参考。
  2. 如果您要在多服务器中部署应用程序,则需要注册服务器。既然您提到这是一个单节点部署,只需在服务器上拉取/构建图像就足够了。但建议使用私有注册表方法。
  3. 我的建议是不要将所有服务合并到一个 docker-compose 文件中。原因是当您使用 docker-compose 文件部署/销毁时,所有服务都将被删除。这是一种紧耦合。当然,我知道所有其他服务都依赖于 DB。在这种情况下,请确保先启动数据库服务,然后再启动其他服务。
  4. 与其指定 env 文件,不如将其作为 Docker 文件指令的一部分。要么复制 env 文件并在入口点获取它,要么使用 ENV 变量来定义它。

也只是一个更新:堆栈只是将服务分组到群中。

所以你的撰写文件应该是:

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"

Dockerfile:

from baseimage:tag
COPY .env /somelocation
# your further instructions go here
RUN ... & \
    ... & \
    ... && chmod a+x /somelocation/.env
ENTRYPOINT source /somelocation/.env && ./file-to-run

替代 Dockerfile:

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>

注意:即使您可以创建@ M.Hassan提到服务,我已经解释了理想的推荐方式。

于 2019-09-22T07:37:06.967 回答