2016-08-04 65 views
5

我已经被开发人员问到我正在为Docker做些与Docker稍有不同的事情,然后我也会使用它。目标是拥有两个容器,其职责如下:命名的Docker卷共享构建不更新

容器A: 将构建前端的节点容器反应应用程序并将该包放入名为app/dist/的目录中。完成后,容器将停止运行。

容器B: 一个高山的nginx容器,它将服务于/usr/share/nginx/html/app的静态文件。

集装箱A中内置的文件将使用卷将提供给容器B,该卷将挂载<Container A>/app/dist<Container B>/usr/share/nginx/html/app

请注意,在公共可访问端口和名为app的容器的nginx容器之间有HAProxy层。

以上正在使用泊坞窗撰写文件,它看起来像下面的精心策划的任务:

version: '2' 
volumes: 
    webapp_build_volume: {} 
services: 
    webapp_build: 
    build: 
     context: . 
     dockerfile: 'config/nginx/dockerfile-builder' 
    volumes: 
     - webapp_build_volume:/app/dist 
     - webapp_static_volume:/app/src/app/static 
    app: 
    build: 
     context: 'config/haproxy' 
     dockerfile: 'dockerfile-app-haproxy' 
    links: 
     - web 
    volumes: 
     - /var/run/docker.sock:/var/run/docker.sock 
    ports: 
     - '80:80' 
     - '1936:1936' 
    web: 
    build: 
     context: . 
     dockerfile: 'config/nginx/dockerfile-web' 
    environment: 
     - EXCLUDE_PORTS=443 
     - VIRTUAL_HOST=* 
    depends_on: 
     - webapp_build 
    volumes: 
     - webapp_build_volume:/usr/share/nginx/html/app 

这是目前工作仅在第一次泊坞窗撰写文件建立。卷创建后卷中的文件不再更新。我已经读过,名为卷在建立后无法更新,但我无法证实这一点。我找到了涉及运行docker-compose rm --force && docker volume webapp_build rm的解决方法,但我希望不必杀死缓存的容器,因为CI服务将变得太慢。

请让我知道,如果我可以澄清任何事情(我知道这里有很多移动部件)。请注意我也在使用docker 2测试版,尽管我没有看到这可以改变我在这里完成的任何事情。

回答

4

这有点难以遵循,但听起来您正在构建映像,将文件输出到您认为是卷的文件中,并尝试使用该文件填充另一个正在运行的容器使用的命名卷。

很可能你的困惑是构建一个容器不会装入卷,卷只能装载到正在运行的容器中。指定的卷确实具有将由映像内容填充的功能,但只有当您装入一个空的已命名卷时才是如此。看起来你正在利用第一次构建+运行中的这个特性,但它在未来的构建中不会再起作用。如果您在没有卷的情况下运行构建容器,则会发现您的文件按预期存在。

您可以轻松更新指定的卷。想到两个选项。一种方法是使用当前进程,但将卷挂载点更改为“/ target”,并将其作为构建容器的CMD,将源代码的内容复制到“/ target”。这将是这样的:

Dockerfile

... 
RUN compile-cmd --output-to /local/build/dir 

entrypoint.sh:

cp -a /local/build/dir/* /target/ 

泊坞窗 - 撰写。阳明:

version: '2' 
services: 
    webapp_build: 
    build: 
     context: . 
     dockerfile: 'config/nginx/dockerfile-builder' 
    volumes: 
     - webapp_build_volume:/target 
... 

第二个选项是在容器构建不能做到这一点在所有的,而是让你的应用程序编译的先决条件的容器。然后将您的应用程序代码作为一个卷装入此容器中,使用CMDENTRYPOINT,该代码将代码卷内容编译并编译,并将其输出到也挂载的指定卷。然后,您只需运行带有两个卷的编译容器,而不是构建构建容器。

entrypoint.sh:

compile-cmd --input-src=/source --output-to /target 

搬运工-compose.yml:

version: '2' 
services: 
    webapp_build: 
    volumes: 
     - app/source:/source 
     - webapp_build_volume:/target 
... 
+0

试图溶液1现在。马上让你知道! – Shawn

+0

谢谢。你的第一个解决方案在那里工为什么这会导致卷更新,但是构建到目录中却没有? – Shawn

+3

您已经构建到目录中,但是在构建过程中未安装卷,这是在运行容器时发生的。在正在运行的容器中安装卷时,当卷的内容为空时,Docker只会将图像中的内容复制到卷中,并且在稍后运行时,该卷的初始化步骤不会执行(否则,您会销毁当您尝试在第二个容器中使用您的音量时的内容)。 – BMitch