Answer a question

What I’d like to do is have 2 Angular apps on the same domain, but serve different files for different paths. For example, browsing to “app1/” will show different content than that on the “app1/test” path. Note: these are default Angular apps, they’re not doing anything special. The only thing I’ve changed the landing page to say “app1” or “app2” to verify that paths hit the correct container.

Additionally, I want anything on the app1/test path to resolve to the same host. So paths like “app1/test” and “app1/test/page1” will lead to the same container. I can get to app1/ with no issues, but I can’t seem to figure out how to route to app1/test correctly. I can browse to it, but it serves the content of app1/ instead of what it’s supposed to. I’ve verified that all of the files I’m creating are inside the container as well, they’re just not being accessed.

Finally, the URL information needs to be in a state that allows nginx to route to the correct container and also allow the angular apps to handle its own virtual routing, without these two interfering with one another.

Here are my config files:

docker-compose.yml


services:

  traefik:
    image: "traefik:v2.4"
    container_name: "traefik"
    command:
      - "--log.level=DEBUG"
      - "--api.insecure=true"
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--entrypoints.web.address=:80"
    ports:
      - "80:80"
      - "8080:8080"
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock:ro"
  app1:
    build:
      context: ./app1
    ports:
      - "8081:80"
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.app1.entrypoints=web"
      - "traefik.http.routers.app1.rule=Host(`localhost`)"
      - "traefik.http.routers.app1.middlewares=app1-stripprefix"
      - "traefik.http.routers.app1.middlewares=app1-autodetect"
      - "traefik.http.middlewares.app1-stripprefix.stripprefix.prefixes=/"
      - "traefik.http.middlewares.app1-autodetect.contenttype.autodetect=false"
      - "traefik.port=80"

  app2:
    build:
      context: ./app2
    ports:
      - "8082:80"
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.app2.entrypoints=web"
      - "traefik.http.routers.app2.rule=Host(`localhost`) && PathPrefix(`/test{regex:$$|/.*}`)"
      - "traefik.http.routers.app2.middlewares=app2-stripprefix"
      - "traefik.http.routers.app2.middlewares=app2-autodetect"
      - "traefik.http.middlewares.app2-stripprefix.stripprefix.prefixes=/test"
      - "traefik.http.middlewares.app2-autodetect.contenttype.autodetect=false"
      - "traefik.port=80"

Dockerfile for both Angular apps


# set working directory
WORKDIR /app

# add `/app/node_modules/.bin` to $PATH
ENV PATH /app/node_modules/.bin:$PATH

# install and cache app dependencies
COPY package.json /app/package.json
RUN npm install
RUN npm install -g @angular/cli@11.0.7

# add app
COPY . /app

# generate build
RUN ng build --output-path=dist

# base image
FROM nginx:1.16.0-alpine

# copy artifact build from the 'build environment'
COPY --from=build /app/dist /usr/share/nginx/html
COPY ./nginx/nginx.conf /etc/nginx/conf.d/default.conf

# expose port 80
EXPOSE 80

# run nginx
CMD ["nginx", "-g", "daemon off;"]

nginx.conf for app1

include /etc/nginx/mime.types;
server {
    listen       80;
    server_name  localhost;
    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }

}

nginx.conf for app2

include mime.types;
include /etc/nginx/mime.types;
server {
    listen       80;
    server_name  localhost;
    location /test {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
}

Answers

I solved my problem. There were a few edits I made along the road, but the final key to the puzzle was a "try_files" line in my nginx.conf files. Read about it here: https://www.nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls/

Here are the updated files:

docker-compose.yml


services:

  traefik:
    image: "traefik:v2.4"
    container_name: "traefik"
    command:
      - "--log.level=DEBUG"
      - "--api.insecure=true"
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--entrypoints.web.address=:80"
    ports:
      - "80:80"
      - "8080:8080"
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock:ro"
  app1:
    build:
      context: ./app1
    ports:
      - "8081:80"
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.app1.entrypoints=web"
      - "traefik.http.routers.app1.rule=Host(`localhost`)"
      - "traefik.http.routers.app1.middlewares=app1-stripprefix"
      - "traefik.http.routers.app1.middlewares=app1-autodetect"
      - "traefik.http.middlewares.app1-stripprefix.stripprefix.prefixes=/"
      - "traefik.http.middlewares.app1-autodetect.contenttype.autodetect=false"
      - "traefik.port=80"

  app2:
    build:
      context: ./app2
    ports:
      - "8082:80"
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.app2.entrypoints=web"
      - "traefik.http.routers.app2.rule=PathPrefix(`/test{regex:$$|/.*}`)"
      - "traefik.http.routers.app2.middlewares=app2-stripprefix"
      - "traefik.http.routers.app2.middlewares=app2-autodetect"
      - "traefik.http.middlewares.app2-stripprefix.stripprefix.prefixes=/test"
      - "traefik.http.middlewares.app2-autodetect.contenttype.autodetect=false"
      - "traefik.port=80"

Dockerfile (for app1)

FROM node:14.15.4 as build

WORKDIR /app

ENV PATH /app/node_modules/.bin:$PATH

COPY package.json /app/package.json
RUN npm install
RUN npm install -g @angular/cli@11.0.7

COPY . /app

RUN ng build --output-path=dist

FROM nginx:1.16.0-alpine

COPY --from=build /app/dist /usr/share/nginx/html
COPY ./nginx/nginx.conf /etc/nginx/conf.d/default.conf

EXPOSE 80

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

Dockerfile for app2

FROM node:14.15.4 as build

WORKDIR /app

ENV PATH /app/node_modules/.bin:$PATH

COPY package.json /app/package.json
RUN npm install
RUN npm install -g @angular/cli@11.0.7

COPY . /app

RUN npm install
RUN npm install --save-dev @angular-devkit/build-angular
RUN ng build --base-href /test --deploy-url /test/ --output-path=dist

FROM nginx:1.16.0-alpine

COPY --from=build /app/dist /usr/share/nginx/html/test
COPY ./nginx/nginx.conf /etc/nginx/conf.d/default.conf

EXPOSE 80

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

nginx.conf for app1

include mime.types;
include /etc/nginx/mime.types;
server {
    listen       80;
    server_name  localhost;
    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
        try_files $uri $uri/ /index.html;
    }
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
}

nginx.conf for app2

include mime.types;
include /etc/nginx/mime.types;
server {
    listen       80;
    server_name  localhost;
    location /test {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
        try_files $uri $uri/ /test/index.html;
    }
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
    location /.ico {
        root   /usr/share/nginx/html;
        add_header Content-Type     image/x-icon;
    }
}
Logo

开发云社区提供前沿行业资讯和优质的学习知识,同时提供优质稳定、价格优惠的云主机、数据库、网络、云储存等云服务产品

更多推荐