繁体   English   中英

Docker Node.js 与 nginx

[英]Docker Node.js with nginx

我尝试 dockerzied node.js, pm2

这是我的 Dockerfile

FROM node:14.17.0 AS build

# Set working directory
WORKDIR /usr/app

# Install PM2 globally
RUN npm install --global pm2
RUN cd /usr/app && ls
# Credential for real time monitoring PM2 Plus
ENV PM2_PUBLIC_KEY xxxxx
ENV PM2_SECRET_KEY xxxxx


# Copy "package.json" and "package-lock.json" before other files
# Utilise Docker cache to save re-installing dependencies if unchanged
COPY ./package*.json ./

# Install dependencies
RUN npm install

# Copy all files
COPY ./ ./

# Build app
RUN npm run-script build

# Expose the listening port
EXPOSE 3000

# Launch app with PM2
CMD [ "pm2-runtime", "start", "npm", "--", "start" ]


FROM nginx:alpine

# ## Replace the default nginx index page with our Angular app
RUN rm -rf /usr/share/nginx/html/*
RUN ls
COPY --from=build  /usr/app /usr/share/nginx/html

COPY ./.nginx/nginx.conf /etc/nginx/nginx.conf

ENTRYPOINT ["nginx", "-g", "daemon off;"]

它在没有 nginx 的情况下工作并成功运行,但是当我尝试 proxy_pass 时出现错误。

nginx

# Run as a less privileged user for security reasons.
user nginx;

# #worker_threads to run;
# "auto" sets it to the #CPU_cores available in the system, and
# offers the best performance.
worker_processes    auto;

events { worker_connections 1024; }

http {
    server {
        # Hide nginx version information.
        server_tokens off;

        listen  80;
        root /usr/share/nginx/html/public;
        include /etc/nginx/mime.types;

        location / {
                proxy_pass http://localhost:3000;
             #   try_files $uri $uri/ /index.php$is_args$args;
                proxy_http_version 1.1;
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection 'upgrade';
                proxy_set_header Host $host;
                proxy_cache_bypass $http_upgrade;
        }

        gzip            on;
        gzip_vary       on;
        gzip_http_version  1.0;
        gzip_comp_level 5;
        gzip_types
                        application/atom+xml
                        application/javascript
                        application/json
                        application/rss+xml
                        application/vnd.ms-fontobject
                        application/x-font-ttf
                        application/x-web-app-manifest+json
                        application/xhtml+xml
                        application/xml
                        font/opentype
                        image/svg+xml
                        image/x-icon
                        text/css
                        text/plain
                        text/x-component;
        gzip_proxied    no-cache no-store private expired auth;
        gzip_min_length 256;
        gunzip          on;
    }
}

当我添加 nginx conf 并运行时

docker run -d -p 3000:3000 test/test

出现错误 502。我的问题是什么? 为什么它不工作proxy_pass。 没有 proxy_pass 工作正常,在 3000 端口我的问题是什么? 为什么它不工作proxy_pass。 没有 proxy_pass 工作正常,在 3000 端口

Dockerfile 只构建一个映像,通常是在最后一个构建阶段(从最后的FROM行开始)。 因此,在您的情况下,正在构建的映像包含 Nginx 服务器和已编译的前端应用程序。 它不包含单独的节点服务器,并且容器内没有任何东西正在监听端口 3000。

我会在这里建议两种可能的方法之一。

如果您的应用程序类似于 React 或 Angular 纯前端应用程序,请保持此设置不变。 第一阶段本身永远不会运行,因此您不需要CMD 删除proxy_pass Nginx 配置选项(可能还有整个自定义 Nginx 配置)并只提供 static 文件。

另一方面,如果您的应用程序更像是 Express 后端服务,那么您需要将其作为两个独立的容器运行。 这是一个更复杂的过程:

首先,将这个 Dockerfile 一分为二。 我可能让Dockerfile只是后端应用程序(我可能会删除不必要的pm2设置,并且绝对不会通过 Dockerfile ENV泄漏凭据)。 第二个Dockerfile.nginx将从第一个图像中复制 static 资产; 我可能会稍微简化 Dockerfile

# Dockerfile.nginx
FROM nginx:alpine
COPY --from=my-name/my-app /usr/app/dist/ /usr/share/nginx/html/
COPY ./.nginx/nginx.conf /etc/nginx/nginx.conf

(只要构建的应用程序包含index.html它将覆盖默认内容;基础映像的CMD被继承,您无需重新声明它。)

在Nginx配置中设置proxy_pass http://backend:3000/; 保留try_files行,或者为/static/assets路径添加单独的路由,如果这些文件在图像中。

最后,编写一个 Docker Compose setup 来一起启动两个容器:

version: '3.8'
services:
  backend: # <-- this name matches proxy_pass
    build: .
    image: my-name/my-app # <-- this name matches COPY --from=
    # ports: ['3000:3000']  # optional
  proxy:
    build:
      context: .
      dockerfile: Dockerfile.nginx
    ports:
      - '8080:80'
    depends_on:
      - backend

您需要分两步构建映像; 先构建后端镜像,再构建代理镜像。 Compose 没有任何本地方式来理解其中一个图像取决于另一个图像的内容。

docker-compose build backend
docker-compose build
docker-compose up -d

Compose会自动为您创建一个网络,因此这两个容器可以使用它们的服务名称backendproxy作为主机名相互通信。 (您将看到许多手动配置networks:container_name:的示例,但这些选项不是必需的。)您可以在http://localhost:8080上连接到已构建的应用程序; 在 Compose ports:选项中,第一个端口号与 URL 中的端口号匹配,第二个端口号与 Nginx listen指令(容器内运行服务器的端口)匹配。 我已经注释掉了第二个ports:行,它允许您绕过代理直接访问后端服务,如果您觉得这很有用的话。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM