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

标签 angular docker nginx docker-compose routes

我的问题

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

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

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

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

鉴于此,我想知道:

how to route angular app properly inside a docker container ?



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

整个搭建过程

我的应用程序由三个服务组成:
  • Angular 前端(Nginx + Angular)
  • 后端 API ( NodeJs + Express )
  • 数据库 (MongoDB)


  • 1) 上下文

    我有以下文件树:
    |frontend
    ||package.json
    ||nginx.conf
    ||frontend.dockerfile
    ||Jumble
    |backend
    ||package.json
    ||backend.dockerfile
    ||server.js
    ||Jumble
    |docker-compose.yml
    

    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"
    

    我的前端 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
    

    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;
      }
    }
    

    后端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"]
    

    2) 构建

    我在主文件夹中构建了我的应用程序,如下所示:
    sudo docker-compose build
    sudo docker-compose up
    

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

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


  • 3)前端路由问题

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

    4) 隔离容器

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

    我将目录更改为文件夹/frontend 并输入:
    sudo docker build -t mytag -f clockmachine-frontend.dockerfile .
    sudo docker run mytag
    

    构建过程大约需要 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 上正常运行 Angular 路由完美运行!

    6) 结论

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

    最佳答案

    终于,经过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
    

    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;
      }
    }
    

    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"
    

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

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

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

    检查此链接:
  • Angular deployment Documentation
  • Dan Wahlin example
  • Serving static content with nginx
  • Nginx.org documentation
  • 关于angular - 如何在 Nginx 容器内路由 Angular 应用程序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61800182/

    相关文章:

    json - nginx 返回带有状态码的 json 文件

    PHP-cgi 随机停止工作,没有错误日志

    Angular 4 隐式流回调和 Router Guard

    angular - ngIf 单行 if 语句 | Angular 6

    javascript - 随机播放对象对象或在模板中的 Angular 2 中随机显示元素

    python - Django-Docker-应用程序默认凭据不可用

    javascript - Angular 2 observable 订阅箭头函数变得又大又脏

    java - 微服务应用程序的 kubernetes 架构 - 建议

    docker - 如何自动缩放 Helm chart 状态集

    php - 通过 Docker 容器和 Nginx Web 服务器在 Laravel 中获取用户的 IP 地址