作者:kafei | 来源:互联网 | 2023-01-18 14:24
我有一个琐碎的node.js码头工人应用程序。
我能够成功运行它,但是尽管按照docker-compose docs中的说明安装了卷,但是在容器内部重新加载代码仍然无法正常工作。
目录布局:
my-test-app
| docker-compose.yml
| Dockerfile
| index.js
| package.json
Dockerfile:
FROM mhart/alpine-node:8
WORKDIR /app
COPY . .
EXPOSE 5000
CMD ["node", "index.js"]
docker-compose.yml:
version: '3'
services:
node-app:
build: .
ports:
- "5000:5000"
volumes:
- .:/app
redis:
image: "redis:alpine"
index.js:
const http = require('http');
const server = http.createServer((req, res) => {
res.end("hello world");
});
server.listen(5000);
package.json:
{
"name": "my-test-app",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
},
"author": "",
"license": "MIT"
}
我也尝试了以下相同的结果(应用运行,无法实时重新加载代码)
使用官方节点图片,而不是alpine-node
。
将应用程序代码放在./app
内部的文件夹下,my-test-app
并相应地更新COPY
内部Dockerfile
和volumes
内部docker-compose.yml
。
Kryten..
6
我看到过短语“实时重载”用于两种不同类型的重载:
代码更改时终止并重新启动应用程序,以及
代码更改后,会自动在客户端浏览器上重新加载HTML和资产。
根据您的问题,我认为您指的是第一种类型,因此下面的答案可以解决该问题。
这里的问题是上下文之一。
请记住,docker容器与您的主机是隔离的-特别是,容器中运行的进程与主机上运行的进程是不同的(通常不能与之交互)。在您的情况下,您已选择在容器中装载主机目录,但这只是文件系统,而不是进程。
考虑一下实例化新容器时Docker映像的作用:它在node index.js
中运行WORKDIR
。代码在哪里停止并在代码更改时重新启动?大概它正在主机上的一个进程中运行。这意味着它无法接触容器中运行的节点进程(因为它是隔离的)。
现在,您还没有提到要使用哪种方法来处理实时重新加载,但这并没有太大的区别。它们基本上都以相同的方式工作:更改应用程序代码后,终止现有进程并开始一个新进程。
要解决此问题,您有两种选择:
在容器中运行“实时重新加载”代码,或者
在容器外运行开发代码
首先,您可以遵循@MarkS的建议并使用nodemon
。这应该像更换一样简单
CMD ["node", "index.js"]
在你的Dockerfile中
CMD ["nodemon", "index.js"]
当然,前提是您已经nodemon
正确安装了映像。
替代方法(这就是我的工作)是在开发过程中在Docker环境外部的主机上运行代码,然后在部署时将其打包为映像。这解决了两个问题:
您在隔离节点进程中遇到的问题,以及
权限问题。
请记住,在Docker中运行的应用程序以方式运行root
。这意味着,如果您的应用创建文件,它们将归拥有root
。我曾尝试在Docker环境中进行开发,但对一些问题感到沮丧,例如,我想删除该应用程序创建的文件,而不得不sudo
(以身份登录root
)只是为了清理东西。
1> Kryten..:
我看到过短语“实时重载”用于两种不同类型的重载:
代码更改时终止并重新启动应用程序,以及
代码更改后,会自动在客户端浏览器上重新加载HTML和资产。
根据您的问题,我认为您指的是第一种类型,因此下面的答案可以解决该问题。
这里的问题是上下文之一。
请记住,docker容器与您的主机是隔离的-特别是,容器中运行的进程与主机上运行的进程是不同的(通常不能与之交互)。在您的情况下,您已选择在容器中装载主机目录,但这只是文件系统,而不是进程。
考虑一下实例化新容器时Docker映像的作用:它在node index.js
中运行WORKDIR
。代码在哪里停止并在代码更改时重新启动?大概它正在主机上的一个进程中运行。这意味着它无法接触容器中运行的节点进程(因为它是隔离的)。
现在,您还没有提到要使用哪种方法来处理实时重新加载,但这并没有太大的区别。它们基本上都以相同的方式工作:更改应用程序代码后,终止现有进程并开始一个新进程。
要解决此问题,您有两种选择:
在容器中运行“实时重新加载”代码,或者
在容器外运行开发代码
首先,您可以遵循@MarkS的建议并使用nodemon
。这应该像更换一样简单
CMD ["node", "index.js"]
在你的Dockerfile中
CMD ["nodemon", "index.js"]
当然,前提是您已经nodemon
正确安装了映像。
替代方法(这就是我的工作)是在开发过程中在Docker环境外部的主机上运行代码,然后在部署时将其打包为映像。这解决了两个问题:
您在隔离节点进程中遇到的问题,以及
权限问题。
请记住,在Docker中运行的应用程序以方式运行root
。这意味着,如果您的应用创建文件,它们将归拥有root
。我曾尝试在Docker环境中进行开发,但对一些问题感到沮丧,例如,我想删除该应用程序创建的文件,而不得不sudo
(以身份登录root
)只是为了清理东西。