我对Docker和NGINX完全陌生,所以我基本上是边走边学。我试图让我的Dockerized MERN应用程序设置为生产(不是一个关键的应用程序,只是为了我的学习目的),在阅读了无数的教程后,我已经得到了我的应用程序只为开发环境。然而,正如标题所示,我想让它在一个产品类型的环境中工作(考虑在AWS中托管),所以我需要更多地优化它。
我会给你看我的Dockerfile.prod的前端:
FROM node:18-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
FROM nginx
# Copy build assets from build/ folder & place them in nginx/html
COPY --from=build /app/build /usr/share/nginx/html
EXPOSE 80
字符串
我的生产NGINX配置文件:
upstream client {
server client:3000;
}
upstream api {
server api:3001;
}
server {
listen 80;
location / {
root /usr/share/nginx/html;
include /etc/nginx/mime.types;
try_files $uri $uri/ /index.html;
}
location /sockjs-node {
proxy_pass http://client;
proxy_http_version 1.1;
# setting 'Upgrade' allows a tunnel setup between client & proxied server http://nginx.org/en/docs/http/websocket.html
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
}
location /api {
proxy_pass http://api;
}
}
型
我的Dockerfile.prod for NGINX
FROM nginx
COPY ./prod.conf /etc/nginx/conf.d/default.conf
型
最后,我的docker-compose.prod.yml文件:
version: '3'
services:
nginx:
depends_on:
- api
- client
restart: always
build:
dockerfile: Dockerfile.prod
context: ./nginx
ports:
- "3000:80"
api:
build:
dockerfile: Dockerfile
context: ./backend
volumes:
- '/app/node_modules'
- './backend:/app'
command: npm start
client:
build:
dockerfile: Dockerfile.prod
context: ./frontend
volumes:
- '/app/node_modules'
- './frontend:/app'
environment:
- WDS_SOCKET_PORT=0
tty: true
stdin_open: true
型
根据我的理解,NGINX容器首先使用其www.example.com构建Dockerfile.prod,因此使用我制作的prod.conf覆盖其默认的.conf文件。然后在构建'client'容器(我的前端)并执行其各自的www.example.com时Dockerfile.prod,构建内容将被复制到NGINX的html文件夹中。所以从技术上讲,“欢迎使用NGINX”屏幕应该被覆盖了,对吗?
然而,当检查复制构建内容的位置时,情况似乎并非如此(请参阅NGINX Image /usr/share/nginx/html contents)。就其价值而言,客户端容器似乎是在NGINX容器之前构建的,至少从我看到的打印出日志的顺序来看(参见Docker Compose Output)。无论如何,似乎我做错了什么,我唯一的预感是前端www.example.com的NGINX部分Dockerfile.prodNGINX的Dockerfile.pro的执行覆盖。有人能帮帮我吗我只是在这一点上超越困惑。
目录结构:
.
├── frontend
│ ├── Dockerfile
│ ├── Dockerfile.prod
│ ├── babel.config.json
│ ├── nginx
│ │ └── default.conf
├── nginx
│ ├── Dockerfile
│ ├── Dockerfile.prod
│ ├── default.conf
│ └── prod.conf
├── docker-compose.prod.yml
├── docker-compose.yml
型
Docker Compose Output的
NGINX Image /usr/share/nginx/html contents的
2条答案
按热度按时间oyt4ldly1#
让我们从为生产提供react应用程序开始,我推荐以下教程:https://dev.to/thexdev/dockerize-production-reactjs-3ai9
因此,您可能需要以下
Dockerfile.prod
:字符串
您需要创建的
default.conf
文件应该如下所示:型
我还建议在Dockerfile所在的目录下创建一个
.dockerignore
文件,内容如下:型
这样您就不会将该文件夹复制到映像中-它是由
npm i
命令自己创建的。这样你就有了一个生产React应用程序。
然后你应该编辑你的
docker-compose.prod.yml
:型
这样你就有了一个nginx示例,它应该作为一个代理,将你的请求路由到API或客户端容器。
要做到这一点,你需要创建
sites-enabled
目录,你的docker-compose.prod.yml
文件就在其中(这样它就可以作为卷挂载到nginx容器中)。在该文件夹中,您需要创建一个包含以下内容的<anyname>.conf
文件:型
这将是一个生产设置。每个服务都有一个镜像和一个nginx容器,它接收请求并将其路由到相应的服务。你不应该在客户端容器中使用nginx示例来将请求路由到API容器,这是不好的做法。您的客户端镜像中的nginx仅用于使此容器成为独立容器,它不应与外部交互。
hgncfbus2#
我想先说@Geilmaker的答案是正确的答案。不过,我也想给予额外的细节,以防任何人有类似的设置。
正如Geilmaker指出的,主要问题是我实际上有两个nginx镜像(一个包含React部分的构建内容)。第一个是在Dockerfile.prod为前端创建的,另一个是在docker-compose.prod.yml执行期间创建的:
字符串
但我没有暴露nginx镜像的构建内容。相反,我公开了一个只有默认配置的版本。此外,由于前端的Dockerfile.prod只运行了'npm run build',因此React应用程序没有被提供服务& prod.conf被配置为默认为任何默认位置的index.html-此时只有欢迎页面。
因此,我必须做的是依靠为Dockerfile.prod创建的nginx代理来进行前端,并将用于prod.conf的一些配置添加到驻留在Frontend文件夹中的default.conf中(例如Express API的代理)。
结果如下:
前端/Dockerfile.prod
型
frontend/nginx/default.conf
型
docker-compose.prod.yml看起来像:
型
请注意'nginx'定义的删除&'client'定义中出现的端口Map。
执行时
docker-compose -f docker-compose.prod.yml up
我终于可以看到我的React应用程序了。再次感谢@Geilmaker🙏