如何在单个Docker容器中部署Angular应用程序和REST Api?

时间:2019-02-27 14:32:11

标签: angular docker deployment docker-compose web-deployment

我有一个与this one非常相似的问题。

我确实有一个Angular应用程序,该应用程序收集数据,然后通过REST Api处理这些数据。我可以很高兴地对这两个应用程序进行docker化,它们在本地运行良好,但是,当我尝试部署它们以使它们可以从“任何地方”访问时,我只能到达前端,但是与REST Api的连接不起作用。

在Angular应用程序中,我有一个文件baseurl.ts。那只包含:

export const baseURL = 'http://localhost:3000/';

我使用以下方法准备好应用程序的生产

ng build --prod

这将创建dist文件夹,然后创建以下docker容器(取自here):

FROM node:alpine AS builder

ARG PROXY=http://myproxy
ARG NOPROXY=localhost,127.0.0.1

ENV http_proxy=${PROXY}
ENV https_proxy=${PROXY}
ENV NO_PROXY=${NOPROXY}
ENV no_proxy=${NOPROXY}

WORKDIR /app

COPY . .

RUN npm install && \
    npm run build

FROM nginx:alpine

COPY --from=builder /app/dist/* /usr/share/nginx/html/

我使用以下容器构建容器

docker build -t form_angular:v1

并使用

运行它
docker run -d -p8088:80 form_angular:v1

REST Api的第二个Dockerfile看起来像这样:

FROM continuumio/miniconda3

ARG PROXY=http://myproxy
ARG NOPROXY=localhost,127.0.0.1

ENV http_proxy=${PROXY}
ENV https_proxy=${PROXY}
ENV NO_PROXY=${NOPROXY}
ENV no_proxy=${NOPROXY} 

COPY my_environment.yml my_environment.yml
SHELL ["/bin/bash", "-c"] 

RUN echo "Using proxy $PROXY" \
    && touch /etc/apt/apt.conf \
    && echo "Acquire::http::Proxy \"$PROXY\";" >> /etc/apt/apt.conf \
    && cat /etc/apt/apt.conf \
    && apt-get -q -y update \
    && DEBIAN_FRONTEND=noninteractive apt-get -q -y upgrade \
    && apt-get -q -y install \
       build-essential \        
    && apt-get -q clean \
    && rm -rf /var/lib/apt/lists/*

RUN ["conda", "env", "create", "-f", "my_environment.yml"]
COPY user_feedback.py user_feedback.py
CMD source activate my_environment; gunicorn -b 0.0.0.0:3000 user_feedback:app

建筑物:

docker build -t form_rest:latest .

运行:

docker run --name form_rest -d -p 3000:3000

正如我所说,在localhost上运行时,所有功能都可以按预期运行。现在如何使这两个容器相互通信以进行“全局”部署?

2 个答案:

答案 0 :(得分:1)

您的baseURL被硬编码为localhost。对于“全局”部署,您需要更改baseURL以指向REST api的全局端点。这将需要您知道全局端点,并且它必须是静态的。

另一种选择是将prod的baseURL设置为/ api,并将有角的nginx配置为将/ api代理到您的REST api。您需要链接容器才能正常工作,但不需要在REST api容器上公开公共端口,只需通过nginx代理它即可。

我在项目中使用nginx代理选项,并使用docker-compose处理所有链接和容器间通信。

docker-compose.yml和nginx.conf文件示例。取自我目前正在使用的东西,认为它应该对您有用。

docker-compose.yml

version: '3.4'
services:
  nginx:
    container_name: nginx
    image: form_angular
    build:
      context: .
      dockerfile: <path to angular/nginx dockerfile>
    ports:
      - 8088:80
    networks:
      - my-network
  restapi:
    container_name: restapi
    image: form_rest
    build:
      context: .
      dockerfile: <path to rest dockerfile>
    networks:
      - my-network
networks:
  my-network:
    driver: bridge

nginx.conf:

events {
  worker_connections 1024;
}
http {
  upstream api {
    server restapi:3000;
  }
  server {
    server_name nginx;
    root /usr/share/nginx/html;
    index index.html;
    include /etc/nginx/mime.types;
    location /api/ {
      proxy_pass http://api;
      proxy_http_version 1.1;
      proxy_set_header Upgrade $http_upgrade;
      proxy_set_header Connection 'upgrade';
      proxy_set_header Host $host;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header X-NginX-Proxy true;
      proxy_cache_bypass $http_upgrade;
    }
    location /assets/ {
      access_log off;
      expires 1d;
    }
    location ~ \.(css|js|svg|ico)$ {
      access_log off;
      expires 1d;
    }
    location / {
      try_files $uri /index.html;
    }
  }
}

答案 1 :(得分:0)

在容器中使用localhost时,表示容器本身,而不是运行容器的主机。 因此,如果您从第二个容器(在您的情况下为UI)指向“ localhost”,则该新容器将查看自身,而找不到API。

解决问题的一种方法是使容器按名称可达。

在您的情况下,最简单的方法是使用docker-compose: 例如:

version: '3'
  services:
    angular:
      image: "form_angular:v1"
      container_name: "form_angular"
      ports:
        - "8088:80"
      external_links:
        - restapi

    restapi:
      image: "form_rest:latest"
      container_name: "form_rest"
      ports:
        - "3000:3000"
      external_links:
        - angular

因此,您可以使用名称(作为DNS)restapiangular来从restapi到达restapi。

我建议您在https://docs.docker.com/compose/

阅读更多有关docker-compose的信息。

它非常通用且容易,您可以使用它很长时间,直到您决定构建自己的云;)