多个容器之间的Docker命名卷

Pau*_*ita 6 volumes docker docker-compose

我想将一些服务部署到我的服务器中,并且所有服务都将使用 nginx 作为 Web 服务器,每个项目都有自己的 .conf 文件,我想与 nginx 容器共享所有这些。我尝试使用命名卷,但是当它被多个容器使用时,数据会被替换。我想从不同的容器中获取所有这些 .conf 文件并将其放入一个卷中,以便 nginx 容器可以读取它。我还尝试在命名卷中使用子目录,但是,使用 namedVolumeName/path 不起作用。

Obs:我在所有项目中都使用 docker-compose

version: "3.7"

services:
  backend:
    container_name: jzmimoveis-backend
    image: paulomesquita/jzmimoveis-backend
    command: uwsgi --socket :8000 --wsgi-file jzmimoveis/wsgi.py
    volumes:
      - nginxConfFiles:/app/nginx
      - jzmimoveisFiles:/app/src
    networks:
      - jzmimoveis
    restart: unless-stopped
    expose:
      - 8000

  frontend:
    container_name: jzmimoveis-frontend
    image: paulomesquita/jzmimoveis-frontend
    command: serve -s build/
    volumes:
      - nginxConfFiles:/app/nginx
    networks:
      - jzmimoveis
    restart: unless-stopped
    expose:
      - 5000

volumes:
  nginxConfFiles:
    external: true
  jzmimoveisFiles:
    external: true
networks:
  jzmimoveis:
    external: true
Run Code Online (Sandbox Code Playgroud)

例如,在这种情况下,我将前端和后端 nginx 文件都链接到命名卷 nginxConfFiles,但是,当我docker-compose up -d在这个文件中这样做时,只有一个 .conf 文件出现在卷中,我认为它会被另一个容器覆盖同一个文件。

Ict*_*tus 9

可能您可以在 nginx 容器上拥有指向 的共享卷/etc/nginx/conf.d,然后为每个项目 conf 文件使用不同的名称。

在概念验证下面,三台服务器,每台服务器上都附加了一个配置文件,以及一个共享卷绑定到的代理(您的 Nginx)/config

version: '3'

services:
  server1:
    image: busybox:1.31.1
    volumes:
    - deleteme_after_demo:/config
    - ./server1.conf:/app/server1.conf
    command: sh -c "cp /app/server1.conf /config; tail -f /dev/null"

  server2:
    image: busybox:1.31.1
    volumes:
    - deleteme_after_demo:/config
    - ./server2.conf:/app/server2.conf
    command: sh -c "cp /app/server2.conf /config; tail -f /dev/null"

  server3:
    image: busybox:1.31.1
    volumes:
    - deleteme_after_demo:/config
    - ./server3.conf:/app/server3.conf
    command: sh -c "cp /app/server3.conf /config; tail -f /dev/null"

  proxy1:
    image: busybox:1.31.1
    volumes:
    - deleteme_after_demo:/config:ro
    command: tail -f /dev/null

volumes:
  deleteme_after_demo:
Run Code Online (Sandbox Code Playgroud)

让我们创建 3 个要包含的配置文件:

? echo "server 1" > server1.conf
? echo "server 2" > server2.conf
? echo "server 3" > server3.conf
Run Code Online (Sandbox Code Playgroud)

然后:

? docker-compose up -d                  
Creating network "deleteme_default" with the default driver
Creating deleteme_server2_1 ... done
Creating deleteme_server3_1 ... done
Creating deleteme_server1_1 ... done
Creating deleteme_proxy1_1  ... done
Run Code Online (Sandbox Code Playgroud)

最后,让我们验证可以从代理容器访问配置文件:

? docker-compose exec proxy1 sh -c "cat /config/server1.conf"
server 1

? docker-compose exec proxy1 sh -c "cat /config/server2.conf"
server 2

? docker-compose exec proxy1 sh -c "cat /config/server3.conf"
server 3
Run Code Online (Sandbox Code Playgroud)

我希望它有帮助。干杯!

注意:您应该看到以与使用 Unix mount 命令完全相同的方式安装卷。如果挂载点中已经有内容,则挂载后您将看不到它,而是看到已挂载设备的内容(除非它是空的并且首先在此处创建)。无论您想看到什么,都必须已经在设备上,否则您需要在之后移动它。

所以,我通过挂载文件来做到这一点,因为我使用的容器中没有数据。然后用开始命令复制这些。您可以通过不同的方式解决它,例如通过在您的映像中使用入口点脚本将配置文件复制到安装的卷。


BMi*_*tch 5

命名卷在空/新时初始化,并使用该卷启动容器。初始化来自图像文件系统,之后,命名卷是持久的,并将保留之前使用的状态。

在这种情况下,您拥有的是竞争条件。卷正在共享文件,但它取决于哪个容器组合首先启动来控制使用哪个映像来初始化卷。命名卷在多个图像之间共享,它只是您想要不同的内容。

对于您的用例,您最好在镜像构建和入口点中放置一些逻辑,以便在构建时将要镜像到卷中的文件保存到镜像中的不同位置,然后在容器启动时更新该卷。通过将其移出命名卷初始化步骤,您可以避免竞争条件,并允许使用来自图像的未来更改来更新卷。这方面的一个示例是在我的基础映像中save-volume您将在 Dockerfile 中运行,并load-volume在您的入口点中运行。

作为旁注,在不需要写入配置文件的容器中将该命名卷挂载为只读也是一个好习惯。