我正在使用docker-compose在我的本地环境中创建构建我的图像,但我遇到了一些问题。
看起来在执行docker-compose up
时,除非我在Docker之外的项目中本地安装了所有软件包,否则Docker compose不会运行。
以下是情景。
我有一个包含{(1}})
的简单index.js
文件
express
用于构建图像的Dockerfile
const app = require('express')();
app.get('/health', (req, res) => res.status(200).send('ok'));
app.listen(8080, () => console.log('magic happens here'));
启动项目的FROM node:6.9.5
RUN mkdir -p /var/log/applications/test_dc
RUN mkdir /src
WORKDIR /src
COPY package.json /src
COPY . /src
RUN npm install
VOLUME ["/src", "/var/log/applications/test_dc"]
EXPOSE 8080
CMD ["npm", "start"]
文件(我删除了链接的图片以保持最小化)
docker-compose.yml
任何人都可以克隆存储库并运行docker compose命令:
这意味着我不需要在docker之外的本地项目中运行version: "2.1"
services:
api:
build: .
container_name: test_dc
ports:
- "8080:8080"
volumes:
- .:/src
。
然而npm install
然而,当我在本地运行docker-compose up
时,这就解决了。
这不是针对Docker的整个想法吗?项目应该与系统的其他部分隔离开来吗?
我有什么遗失的吗?
答案 0 :(得分:1)
您似乎希望项目代码能够存在于/src
中,如Dockerfile中所示:
RUN mkdir /src
WORKDIR /src
COPY package.json /src
COPY . /src
但在docker-compose.yml中,您正在将外部路径挂载为/src
。
volumes:
- .:/src
外部安装将优先,并模糊Dockerfile中映像中内置的所有内容(以及您在Dockerfile中定义的卷)。
处理此问题的常用方法是使用在容器启动时运行安装程序的入口点脚本。
entrypoint.sh:
#!/bin/sh
npm install
exec "$@"
Dockerfile:
COPY entrypoint.sh /entrypoint.sh
RUN chmod 755 /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
在容器启动时,将运行入口点脚本,并且已安装外部卷。因此,npm install
可以在那里运行和安装模块。完成后,执行CMD
。在您的情况下,即npm start
。
使用容器的一个原因是创建隔离。也就是说,您希望图像被隔离,而不是依赖于您的外部环境。那么你为什么要使用外部支架?
答案是在开发过程中,您经常希望避免频繁重建。由于映像是不可变的,因此每次更改都需要重建并重新启动容器。所以每个代码都会改变......是的,它会很慢。
一个很好的折衷方案是将图像构建为完全包含,但在开发过程中,您需要在外部安装代码,以便在不进行重建步骤的情况下快速进行更改。准备好发布代码后,可以删除外部装载并执行最终构建。由于您要复制正在装入容器的文件,因此它们都是相同的。构建中的npm install
步骤与您在自定义ENTRYPOINT
中运行的步骤相同。