如何在 Nginx 容器内路由 Angular 应用程序?

Oli*_*ona 8 routes nginx docker docker-compose angular

我的问题

我想用 docker 容器部署我的 angular 应用程序。不幸的是,我很难路由特定的 uri。

前端图像包含 nginx 和我编译的 angular 应用程序。为了在容器内执行路由,nginx 将所有 uri 指向我编译的应用程序,try_files $uri $uri/ myapplication/index.html =404然后 angular router 负责一切。

但是,当我运行前端容器时。我只能访问我的应用程序,而角度路由根本不起作用。

另一方面,如果我在没有 docker 的情况下使用 nginx 为我编译的应用程序提供服务,则路由可以完美运行。

鉴于此,我想知道:

如何在 docker 容器内正确路由 angular 应用程序?

您可以在 Tl;dr 下方找到所有详细信息


整个构建过程

我的应用程序由三个服务组成:

  1. Angular 前端(Nginx + Angular)
  2. 后端 API ( NodeJs + Express )
  3. 数据库(MongoDB)

1) 上下文

我有以下文件树:

|frontend
||package.json
||nginx.conf
||frontend.dockerfile
||Jumble
|backend
||package.json
||backend.dockerfile
||server.js
||Jumble
|docker-compose.yml
Run Code Online (Sandbox Code Playgroud)

Docker-compose.yml 文件:

services:
  frontend:
    container_name: clockmachine-frontend
    build:
      context: ./frontend
      dockerfile: clockmachine-frontend.dockerfile

  database:
    container_name: mongo
    image: mongo
    ports:
    - "27017:27017"

  backend:
    container_name: clockmachine-api
    image: clockmachine-api
    build:
      context: ./backend
      dockerfile: clockmachine-api.dockerfile
    environment:
      - NODE_ENV=production
    ports:
      - "3000:3000"
Run Code Online (Sandbox Code Playgroud)

我的前端 Dockerfile:

#### Stage 0, Build Angular frontend
FROM node:latest as build
WORKDIR /app
COPY package.json package.json
RUN npm install
COPY . .
RUN npm run build -- --prod

####Stage 1, Build Nginx backend
FROM nginx:alpine
COPY --from=build /app/dist/ /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
Run Code Online (Sandbox Code Playgroud)

nginx.conf 文件:

server {
  listen 0.0.0.0:80;
  listen [::]:80;
  default_type application/octet-stream;
  client_max_body_size  256M;

  root /usr/share/nginx/html/myapplication;
  index index.html;

  location / {
    try_files $uri $uri/ /index.html =404;
  }
}
Run Code Online (Sandbox Code Playgroud)

后端dockerfile:

#### Stage 0, Build API
FROM node:alpine
LABEL author="Olivier D'Ancona"
WORKDIR /app
COPY package.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD ["node","server.js"]
Run Code Online (Sandbox Code Playgroud)

2)构建

我在主文件夹中构建了我的应用程序,如下所示:

sudo docker-compose build
sudo docker-compose up
Run Code Online (Sandbox Code Playgroud)

前端将被编译并在 nginx 服务器内提供服务。后端将使用 nodejs 和 express 进行部署。数据库将从 dockerhub 拉取一个 mongo 镜像。

在这一点上,应用程序正在构建没有问题。我控制了我的服务的状态:

  1. http://localhost:27017/与 Mongo db 实例连接(看起来您正在尝试在本机驱动程序端口上通过 HTTP 访问 MongoDB。)
  2. http://localhost:3000/api/也可以正常工作(我成功连接到 mongo 的终端)
  3. http://localhost:8080无法连接(Firefox无法与位于 localhost:8080 的服务器建立连接。)
  4. http://localhost/student这是我的应用程序的静态路由(欢迎使用 nginx!如果您看到此页面,则 nginx 网络服务器已成功安装并正常工作。需要进一步配置。)

3)前端路由问题

所以在这一点上,数据库和后端正在协同工作。我的应用程序在 localhost/myapplication/index.html 上提供服务,但角度路由不起作用,而是浏览器告诉我他无法访问我的应用程序。我发现有人在这里有类似的问题。


4)隔离容器

所以我尝试单独构建和运行前端容器:

我将目录更改为文件夹 /frontend 并输入:

sudo docker build -t mytag -f clockmachine-frontend.dockerfile .
sudo docker run mytag
Run Code Online (Sandbox Code Playgroud)

构建过程大约需要 10 分钟并成功完成。这次当我到达http://localhost/myapplication 时,应用程序运行正常,但再次遇到了这个路由问题。


5)在没有容器的情况下运行nginx

所以,我尝试直接在我的机器上运行 nginx。我编译了我的前端应用程序:

ng build --prod

把它移过去 /usr/share/nginx/html/myapplication

我使用了相同的 nginx.conf 配置文件并将其放入/etc/nginx/conf.d/default.conf,我什至尝试更改文件名而不是覆盖 default.conf 文件。

结果是我的应用程序正常运行localhost/myapplication,角度路由工作完美!


六,结论

总而言之,我尝试运行 docker-compose 文件,但前端容器存在路由问题。然后我隔离了这个容器,它有相同的结果。最后,我直接使用 nginx 为我的应用程序提供服务,并且成功了,因为路由工作正常。

Oli*_*ona 12

终于,经过15天的劳动,我修好了!

问题出listen [::]:80在 nginx 配置中的那一行。此外,前端容器的端口设置不正确。

这就是我实现它的方式:

前端 Dockerfile:

# Stage 0: compile angular frontend
FROM node:latest as build
WORKDIR /app
COPY . . 
RUN npm install
RUN npm run build --prod


# Stage 1: serve app with nginx server
FROM nginx:latest
COPY --from=build /app/dist/pointeuse  /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
Run Code Online (Sandbox Code Playgroud)

nginx配置:

server {
  listen 80;
  sendfile on;
  default_type application/octet-stream;

  gzip on;
  gzip_http_version 1.1;
  gzip_disable      "MSIE [1-6]\.";
  gzip_min_length   256;
  gzip_vary         on;
  gzip_proxied      expired no-cache no-store private auth;
  gzip_types        text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript;
  gzip_comp_level   9;

  root /usr/share/nginx/html;

  location / {
    try_files $uri $uri/ /index.html =404;
  }
}
Run Code Online (Sandbox Code Playgroud)

Docker-compose 文件:

version: '3.1'

services:
        frontend:
                container_name: clockmachine-frontend
                depends_on:
                        - database 
                        - backend
                image: clockmachine-frontend
                build:
                        context: ./frontend
                        dockerfile: frontend.dockerfile
                ports:
                        - "80:80"
        database:
                container_name: mongo
                image: mongo
                ports:
                        - "27017:27017"

        backend:
                container_name: clockmachine-api
                image: clockmachine-api
                build:
                        context: ./backend
                        dockerfile: backend.dockerfile
                environment:
                        - NODE_ENV=production
                ports:
                        - "3000:3000"
Run Code Online (Sandbox Code Playgroud)

如您所见,我重命名了上下文的文件。

使用 nginx 服务器容器化 angular 应用程序是一团糟,因为文档是不同的。

如果你想部署一个 Angular 应用程序

检查此链接:

  1. Angular 部署文档
  2. 丹华林的例子
  3. 使用 nginx 提供静态内容
  4. Nginx.org 文档