我不确定我可能做错了什么,但我有以下script.sh
文件坐在我的项目的根:
script.sh
#!/bin/sh
npm run start
envsubst '$PORT' < /etc/nginx/conf.d/configfile.template > /etc/nginx/conf.d/default.conf
nginx -g 'daemon off;'
然后我在我的Dockerfile
中引用了上面的脚本,如下所示:
Dockerfile
# Build environment
FROM node:16.14.2
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install --only=production
COPY . ./
# server environment
FROM nginx:alpine
COPY nginx.conf /etc/nginx/conf.d/configfile.template
ENV HOST 0.0.0.0
ENV NODE_ENV production
EXPOSE 8080
COPY script.sh /
RUN chmod +x /script.sh
ENTRYPOINT ["/script.sh"]
成功构建Docker映像后,我试图将其作为容器运行,但我一直返回的是以下错误:
/script.sh: line 2: npm: not found
我希望这个脚本能够从环境中获取已经安装的npm。
我能做些什么不同的工作?
你试图运行两个独立的程序,所以在两个不同的容器中运行它们。
# Dockerfile.app
FROM node:16.14.2
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install --only=production
COPY . ./
ENV HOST 0.0.0.0
ENV NODE_ENV production
EXPOSE 8080
CMD npm run start
# Dockerfile.nginx
FROM nginx:alpine
COPY nginx.conf /etc/nginx/conf.d/configfile.template
你可以使用像Docker Compose这样的系统来同时运行这两个部分:
# docker-compose.yml
version: '3.8'
services:
app:
build:
context: .
dockerfile: Dockerfile.app
nginx:
build:
context: .
dockerfile: nginx
ports:
- 8080:80
运行docker-compose up -d
将同时启动两个容器。在您的Nginx配置中,确保使用proxy_pass http://app:8080
,使用Compose服务名称和服务正在侦听的端口号,将请求转发到另一个容器。
nginx
镜像已经知道如何在它自己的入口点脚本中运行脚本中的envsubst
行,并且它已经有一个正确的默认命令。
在你的问题中显示的设置中有两个基本问题,都与试图在同一个容器中运行两个程序有关。首先是你不能合并图像,有第二个FROM
行使Docker从新的基本图像开始。(所以你的最终图像只包含Nginx,而不是Node或你的构建应用程序,因此npm not found
错误。)第二个问题是,脚本将启动应用程序,但直到应用程序退出后才启动Nginx代理。有一些常见的解决方法(比如使用后台进程),但它本质上导致一个进程或另一个进程不受Docker监控,所以你的应用程序可能会失败,而Docker不会注意到它能够重新启动它。