我在Dockerizing a Node.js web app示例中工作,试图从第一原则中理解Docker。我已将server.js
重新命名为index.js
,将其上传到repl.it(由于repl.it强制存在index.js的错误/功能),这里是链接:
项目:https://repl.it/repls/BurlyAncientTrust
现场演示:https://BurlyAncientTrust--five-nine.repl.co
下载:https://repl.it/repls/BurlyAncientTrust.zip
我还整理了一些核心操作,这些操作以功能/声明的方式从图像中获取容器,而不是使用名称(令人惊讶的是,这些没有中心来源):
# commands to start, list, login and remove containers/images associated with current directory's image
# build and run docker image (if it was removed with "docker rmi -f <image>" then this restores IMAGE in "docker ps")
(image=<image_name> && docker build -t $image . && docker run --rm -p <host_port>:<container_port> -d $image)
# list container id for image name
(image=<image_name> && docker ps -a -q --filter=ancestor=$image)
(image=<image_name> && docker ps -a | awk '{print $1,$2}' | grep -w $image | awk '{print $1}')
# run/exec bash inside container (similar to "vagrant ssh")
(image=<image_name> && docker exec -it $(docker ps -a -q -n=1 --filter=ancestor=$image) bash)
# remove containers for image name
(image=<image_name> && docker ps -a -q --filter=ancestor=$image | xargs docker rm -f)
# remove containers and specified image
(image=<image_name> && docker ps -a -q --filter=ancestor=$image | xargs docker rm -f && docker rmi $image)
构建并运行示例:
下载并解压缩BurlyAncientTrust.zip
cd <path_to>/BurlyAncientTrust
然后:
(image=node-web-app && docker build -t $image . && docker run --rm -p 49160:8080 -d $image)
访问:
您应该看到:
Hello world
问题是我无法使用-v
选项进行卷映射(目录同步):
(image=node-web-app && docker ps -a -q --filter=ancestor=$image | xargs docker rm -f && docker rmi $image)
(image=node-web-app && docker build -t $image . && docker run --rm -v "$(pwd)":/usr/src/app -p 49160:8080 -d $image)
我明白了:
This site can’t be reached
docker ps
不再显示容器。我在Mac OS X High Sierra上,所以"$(pwd)"
部分可能在其他平台上有所不同。您可以使用当前工作目录的绝对路径替换它。这是完整的输出:
Zacks-Macbook:hello-system zackmorris$ (image=node-web-app && docker ps -a -q --filter=ancestor=$image | xargs docker rm -f && docker rmi $image)
Untagged: node-web-app:latest
Deleted: sha256:117288d6b7424798766b288518e741725f8a6cba657d51cd5f3157ff5cc9b784
Deleted: sha256:e2fb2f92c1fd4697c1d217957dc048583a14ebc4ebfc73ef36e54cddc0eefe06
Deleted: sha256:d274f86b6093a8e44afe1720040403e3fb5793f5fe6b9f0cf2c12c42ae6476aa
Deleted: sha256:9116e43368aba02f06eb1751e6912e4063326ce93ca1724fead8a8c1e1c6c56b
Deleted: sha256:902d4d1718530f6c7a50dd11331ee9ea85a04464557d699377115625da571b61
Deleted: sha256:261c92dc9ba95e2447e0250ea435717c855c6b184184fa050fc15fc78b1447f8
Deleted: sha256:559b16060e30ea3875772aae28a2c47508dfebda35529e87e7ff46f035669798
Deleted: sha256:4316607ec7e64e54ad59c3e46288a9fb03d9ec149b428a8f70862da3daeed4e5
Zacks-Macbook:hello-system zackmorris$ (image=node-web-app && docker build -t $image . && docker run --rm -v "$(pwd)":/usr/src/app -p 49160:8080 -d $image)
Sending build context to Docker daemon 57.34kB
Step 1/7 : FROM node:carbon
---> baf6417c4cac
Step 2/7 : WORKDIR /usr/src/app
---> Using cache
---> 00b2b9912592
Step 3/7 : COPY package*.json ./
---> f39ed074815e
Step 4/7 : RUN npm install
---> Running in b1d9bf79d502
npm notice created a lockfile as package-lock.json. You should commit this file.
npm WARN docker_web_app@1.0.0 No repository field.
npm WARN docker_web_app@1.0.0 No license field.
added 50 packages in 4.449s
Removing intermediate container b1d9bf79d502
---> cf2a5fce981c
Step 5/7 : COPY . .
---> 46d46102772b
Step 6/7 : EXPOSE 8080
---> Running in cd92fbacacf1
Removing intermediate container cd92fbacacf1
---> ac13f4eda9a2
Step 7/7 : CMD [ "npm", "start" ]
---> Running in b6cd6811b0ce
Removing intermediate container b6cd6811b0ce
---> 06f887984da8
Successfully built 06f887984da8
Successfully tagged node-web-app:latest
effc653267558c80fbcf017d4c10db3e46a7c944997c7e5a5fe5d8682c5c9dad
Docker文件共享:
$ pwd
/Users/zackmorris/Desktop/hello-system
我知道像卷映射那样关键任务必须有效。
更新:我为此打开了issue,看起来可能无法实现(这可能是Docker早期历史中的错误/功能) )。 best answer so far是Dockerfile在RUN npm install
挂载"$(pwd)"
之前调用/usr/src/app
(替换内容),因此/usr/src/app/node_modules
目录被替换为空,导致Node.js崩溃,因为它无法找到导致容器退出的express
模块。
所以我正在寻找能够解决这个问题的答案,并使这个目录映射在一般意义上成为可能,没有任何奇怪的陷阱,比如必须重新排列图像的内容。
答案 0 :(得分:0)
我进一步挖掘了Docker构建时和运行时之间的区别,特别是关于Docker Compose,并偶然发现:
https://blog.codeship.com/using-docker-compose-for-nodejs-development/
他能够通过将node_modules
映射为docker-compose.yml
中的附加音量来使其发挥作用(请注意,我的路径为/usr/src/app
而他的/usr/app/
是volumes:
- .:/usr/app/
- /usr/app/node_modules
所以不要&# 39; t copypaste this):
node_modules
我认为这是有效的,因为它使-v /usr/src/app/node_modules
成为一个重叠的卷,它会保留其中的所有文件而不是覆盖它们。
我尝试将其作为原始Docker命令node_modules
并且它有效!这是一个新的独立示例,与BurlyAncientTrust完全相同,但添加了cd <path_to>/RoundedImpishStructures
目录:
项目:https://repl.it/repls/RoundedImpishStructures
现场演示:https://RoundedImpishStructures--five-nine.repl.co
下载:https://repl.it/repls/RoundedImpishStructures.zip
构建并运行示例:
下载并解压缩RoundedImpishStructures.zip:
(image=node-web-app && docker ps -a -q --filter=ancestor=$image | xargs docker rm -f && docker rmi $image)
如果您正在使用它们,请删除旧容器和图像:
(image=node-web-app && docker build -t $image . && docker run --rm -v "$(pwd)":/usr/src/app -v /usr/src/app/node_modules -p 49160:8080 -d $image)
运行新示例:
Hello world
您应该看到:
<Menu HorizontalAlignment="Left">
<Menu.ItemsPanel>
<ItemsPanelTemplate >
<DockPanel VerticalAlignment="Stretch" LastChildFill="False"/>
</ItemsPanelTemplate>
</Menu.ItemsPanel>
<MenuItem Header="Option A" DockPanel.Dock="Top"/>
<MenuItem Header="Option B" DockPanel.Dock="Top"/>
<MenuItem Header="Option C" DockPanel.Dock="Top"/>
<MenuItem Header="Settings" DockPanel.Dock="Bottom"/>
<MenuItem Header="Logout" DockPanel.Dock="Bottom"/>
</Menu>
请不要赞成这个答案,因为我不相信这是一个普遍的解决方案。希望它可以帮助某人。