Docker-在docker-compose 3

时间:2019-04-12 10:19:55

标签: docker docker-compose

我有两个容器: nginx 角度 angular 容器包含代码,并且在有新版本(带有with望塔)时会自动从注册表中拉出。

我在 angular nginx 之间设置了共享卷,以将代码从 angular 共享到 nginx

  ### Angular #########################################
  angular:
    image: registry.gitlab.com/***/***:staging
    networks:
      - frontend
      - backend
    volumes:
      - client:/var/www/client

  ### NGINX Server #########################################
  nginx:
    image: registry.gitlab.com/***/***/***:staging
    volumes:
      - client:/var/www/client
    depends_on:
      - angular
    networks:
      - frontend
      - backend

volumes:
  client:
networks:
  backend:
  frontend:

当我第一次构建并运行环境时,一切正常。 问题是,当有新版本的 client 客户端,图像被拉出,容器被重新构建并且新的代码版本位于 angular 容器内时,但是在 nginx 容器中,它仍然是 client 的旧代码版本。

共享卷不允许我做我想做的事情,因为我们无法指定谁是主机,是否可以将一个卷从一个容器装载到另一个容器?<​​/ p>

谢谢。

编辑

角度容器仅在此处提供文件。我们可以将已构建的应用程序同步到主机上的服务器,然后将其卷装到容器(主机-> guest虚拟机)上,但这将违反我们的CI流程: build app -> build图片-> 推送到注册表-> watch望塔获取新图片

2 个答案:

答案 0 :(得分:1)

Docker卷不打算共享代码,建议您重新考虑此工作流程。

第一次启动具有空卷的容器,第一次 ,如果卷已经为空,则 ,Docker将populate it with contents from the container 。由于卷旨在保存 data ,并且应用程序可能会更改将要保留的数据,因此,如果容器重新启动,Docker不会覆盖应用程序数据。卷目录中的内容保持不变。

在您的设置中,这意味着会发生这种情况:

  1. 您是第一次启动angular容器,并且由于client命名卷为空,因此Docker将内容复制到其中。
  2. 您启动nginx容器。
  3. 您删除并重新启动angular容器;但是由于client命名的卷为空,因此Docker将旧内容保留在那里。
  4. nginx容器仍然可以看到旧内容。

对于典型的浏览器应用程序,实际上并不需要运行“程序”:一旦您通过Typescript / Webpack / ...序列运行,输出便是完全静态文件的集合。对于Angular,有一个Ahead-of-Time compiler会生成这些静态文件。我在这里建议的顺序是:

  1. 在本地检查您的应用程序源树。
  2. 使用面向开发人员的工具,例如ng servenpm start单独开发浏览器应用程序。由于所有这些都在本地运行,因此您无需与特定于Docker的任何内容(文件系统映射,权限,端口映射等)作斗争。这是一个完全正常的Javascript开发序列。您所需的系统组件仅仅是Node;绝对比安装和配置Docker容易。
  3. 使用Angular AOT编译器或Webpack或npm build将应用程序编译为静态文件。
  4. 将这些静态文件发布到CDN;或将它们绑定安装到nginx容器中;或将它们构建为自定义图像。

在最后一种情况下,您将不使用命名的Docker卷。相反,您可以将本地文件系统挂载到容器中。这种情况下的完整docker-compose.yml文件如下所示:

version: '3'
services:
  nginx:
    image: registry.gitlab.com/***/***/***:staging
    volumes:
      - ./client:/var/www/client
    ports:
      - '8000:80'

答案 1 :(得分:1)

根据您的评论:

  

没有为客户端运行的程序,CI会编译应用程序并构建自定义映像,该映像COPY中的应用程序文件位于/var/www/client中。然后,watch望塔拉出这个新图像并重新启动容器。容器仅在带有({tail -f /dev/null & wait)的守护进程中运行。

从高层次看,我根本不需要两个容器或两个卷。只需使用多阶段构建来构建您的应用程序,该构建会生成具有所需内容的nginx图像:

FROM your_angular_base AS build
COPY src /src
RUN  steps to compile your code

FROM nginx_base as release
...
COPY --from=build /var/www/client/ /var/www/client/
...

然后将撰写文件简化为:

...
  ### NGINX Server #########################################
  nginx:
    image: registry.gitlab.com/***/***/***:staging
    networks:
      - frontend
      - backend

networks:
  backend:
  frontend:

如果确实遇到需要在两个正在运行的容器之间共享卷,并且每次部署其中一个映像都需要更新该卷的情况,那么最好的方法是入口点脚本将文件从一个位置复制到卷中。我的docker-base中有一个使用save-volumeload-volume脚本的例子。