docker-compose" up" vs." run"产生不同的装载量

时间:2017-01-10 13:23:51

标签: node.js npm docker-compose

更新2:我创建了a sample project on Git to reproduce this issue。经过进一步测试,测试用例与我在原帖中所描述的略有不同。

我包含了我在下面的github repo上写的README的内容。

使用案例

  • 一个带有Dockerfile的简单nodejs项目。
  • 上述项目使用的一个本地NPM依赖项(通过Dockerfile复制到容器)。该项目通过local path来引用依赖关系。
  • nodejs项目有一个Web路由(/),它从package.json打印本地npm依赖项的版本。这用于验证测试用例过程的结果。
  • docker-compose使用this volume technique覆盖主机的源树 在容器的源代码树顶部,然后将容器中的node_modules覆盖在第一个卷的顶部。

重现步骤

  1. 克隆this repo
  2. 通过docker rmdocker rmi清除与此repo项目相关的所有先前容器和图片。
  3. 查看test2_run1标记。此状态表示使用本地NPM依赖项1.0.0版的项目。
  4. 做一个docker-compose build。如果正确执行了步骤2,则所有步骤都应该在没有任何缓存使用的情 请注意npm install命令期间本地NPM依赖关系的版本,例如: +-- my-npm@1.0.0
  5. 做一个docker-compose up。浏览到http://localhost:8000。该页面应报告版本1.0.0
  6. 停止正在运行的容器。 (发出up命令的终端上的Ctrl-C。)
  7. 查看test2_run2标记。这会将a small change引入NPM的index.js文件和版本 将package.json添加到1.0.1
  8. 做一个docker-compose build只有COPY ./my-npm ...之前的说明才能使用缓存。(例如,docker输出会为该指令输出---> Using cache。)所有后续步骤都应由docker运行。这是因为步骤7中引入NPM包的更改应该使COPY ./my-npm ...命令的高速缓存无效,因此,后续步骤也是如此。确认在npm install命令期间,新摘要的NPM将打印在摘要树输出中,例如, +-- my-npm@1.0.1
  9. 做一个docker-compose up。浏览到http://localhost:8000。该页面应报告版本1.0.1
  10. 预期行为:步骤9中的页面应报告1.0.1。也就是说,本地npm的变化应该通过docker-compose up反映在容器中。

    实际行为:步骤9中的页面报告1.0.0

    请注意,docker本身正在按预期重新构建图像。观察到的问题不是docker重新使用缓存的图像,而是输出 显示它重新运行NPM安装并显示本地NPM依赖项的新版本。问题是docker-compose没有看到 构成dctest_service1容器的基础图像已更新。

    事实上,在容器中运行bash可以让我们看到容器有更新的my-npm模块文件,但是node_modules 版本陈旧:

    # docker exec -it dctest_service1_1 bash app@6bf2671b75c6:~/service1$ grep version my-npm/package.json node_modules/my-npm/package.json my-npm/package.json: "version": "1.0.1", node_modules/my-npm/package.json: "version": "1.0.0" app@6bf2671b75c6:~/service1$

    解决方法:使用docker rm删除dctest_service1容器。然后重新运行docker-compose up,它将使用现有图像重新创建容器。值得注意的是,此步骤不会重建基础图像。在重新创建容器时,docker-compose似乎想要使用具有更新node_modules的较新卷。

    请参阅output目录,了解第一次运行(步骤4和5)和第二次运行(步骤8和9)期间打印的输出。

    原帖

    我基于this tutorial ("Lessons from Building a Node App in Docker")得到了nodejs Dockerfile。具体来说,请注意本教程使用卷技巧将node_modules目录从容器本身挂载到主机上等效的目录之上。 E.g:

    volumes:
     - .:/home/app/my-app
     - /home/app/my-app/node_modules
    

    我遇到了一个问题,即package.json的更新按预期触发npm install(与使用docker缓存相反),但在使用docker-compose up启动服务时,结果容器以某种方式最终得到了node_modules数据的旧版本,因为目录中缺少新添加的NPM包。但是,如果通过CMD手动运行指定的docker-compose run --rm,那么我执行会看到更新的卷!

    我可以通过以下几种方式确认:

    node_modules时间戳

    容器通过" up":

    启动
    app@88614c5599b6:~/my-app$ ls -l
    ...
    drwxr-xr-x 743 app app 28672 Dec 12 16:41 node_modules
    

    通过"运行"

    启动容器
    app@bdcbfb37b4ba:~/my-app$ ls -l
    ...
    drwxr-xr-x 737 app app 28672 Jan  9 02:25 node_modules
    

    不同docker inspect" Mount"条目号

    容器通过" up":

    启动
    "Name": "180b82101433ab159a46ec1dd0edb9673bcaf09c98e7481aed7a32a87a94e76a",
    "Source": "/var/lib/docker/volumes/180b82101433ab159a46ec1dd0edb9673bcaf09c98e7481aed7a32a87a94e76a/_data",
    "Destination": "/home/app/my-app/node_modules",
    

    通过"运行"

    启动容器
    "Name": "8eb7454fb976830c389b54f9480b1128ab15de14ca0b167df8f3ce880fb55720",
    "Source": "/var/lib/docker/volumes/8eb7454fb976830c389b54f9480b1128ab15de14ca0b167df8f3ce880fb55720/_data",
    "Destination": "/home/app/my-app/node_modules",
    

    HostConfig - >结合

    我不确定这是否相关,但我也注意到(docker inspectBindsHostConfig部分"Binds": [ "180b82101433ab159a46ec1dd0edb9673bcaf09c98e7481aed7a32a87a94e76a:/home/app/my-app/node_modules:rw", "/Volumes/my-mount/my-app:/home/app/my-app:rw" ], 部分在两个案例之间有所不同:

    容器通过" up":

    启动
    "Binds": [
      "/Volumes/my-mount/my-app:/home/app/my-app:rw"
    ],
    

    通过"运行"

    启动容器
    node_modules

    (两者都显示主机信号源安装在图像上,但只有" up"显示带有docker-compose up的辅助叠加音量,这似乎是另一个奇怪的皱纹。)

    理论

    根据docker-compose CLI reference

      

    如果有服务的现有容器和服务   容器创建后,配置或映像已更改,   docker-compose up通过停止和重新创建来获取更改   容器

    因此,看起来--force-recreate认为配置或图像没有改变。我只是不确定如何调试这个来确认。当然,我可以使用docker-compose build来解决这个问题,但我想解决一下我的配置错误导致问题的原因。

    更新:如果我在docker-compose up之前做了明确的Dockefile,问题仍然存在。因此,我现在对这一理论缺乏信心。

    以下是整个FROM node:6.9.1 RUN useradd --user-group --create-home --shell /bin/false app ENV HOME=/home/app ENV APP=my-app ENV NPM_CONFIG_LOGLEVEL warn RUN npm install --global gulp-cli COPY ./package.json $HOME/$APP/package.json RUN chown -R app:app $HOME/* USER app WORKDIR $HOME/$APP RUN npm install && npm cache clean USER root COPY . $HOME/$APP RUN chown -R app:app $HOME/* && chmod u+x ./node_modules/.bin/* ./bin/* USER app ENTRYPOINT ["/home/app/my-app/bin/entrypoint.sh"] CMD ["npm", "run", "start:dev"]

    {{1}}

1 个答案:

答案 0 :(得分:2)

命令docker-compose使用docker-compose.yml文件作为容器service的配置文件。默认情况下,它会在您运行的目录docker-compose中查找此.yml配置文件。 所以可能是你的docker-compose.yml文件不是最新的,因为当你运行docker-compose up时,你的某个卷没有被挂载。

docker run忽略docker-compose.yml文件,只使用Dockerimage构建容器。因此Dockerimage文件和docker-compose.yml文件之间可能存在配置差异。