【问题标题】:How to deploy an Angular application and a REST Api in individual docker containers?如何在单个 docker 容器中部署 Angular 应用程序和 REST Api?
【发布时间】:2019-02-27 14:32:11
【问题描述】:

我有一个与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 上运行时,一切都按预期工作。我现在如何让这两个容器相互通信以进行“全局”部署?

【问题讨论】:

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


    【解决方案1】:

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

    另一种选择是将 baseURL 设置为 /api for prod 并将 angular 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;
        }
      }
    }
    

    【讨论】:

    • 硬编码是我真正想避免的事情,因为每次我想在其他地方部署它时都必须创建一个新图像。第二个选项听起来不错!您能否展示一下上述案例中这样一个 docker-compose 文件的外观?!
    • 用示例更新答案
    • 非常感谢!我只能在明天测试它;然后我回复你并支持/接受。 :)
    • 几个问题:如果我使用dockerfile: folder/Dockerfile,它会即时构建名为form_angular 的图像,即build 是什么,因为我已经有图像了?其次,这个nginx.conf 文件在哪里,即在这种情况下我与它有什么关系?谢谢!
    • 如果您没有预先构建的映像,docker-compose 将为您构建它。您还可以将标志传递给 docker-compose,让它在开始之前为您手动构建映像。要回答您的第一个问题,是的,这应该有效。如果您不希望 docker-compose 构建您的图像,您可以删除构建部分。我在 docker-compose.yml 中编辑了服务名称,nginx.conf 中第 6 行中的服务器引用需要与您要指向的服务名称匹配。您需要在 nginx dockerfile 中添加一个复制行,将配置文件复制到 /etc/nginx/nginx.conf
    【解决方案2】:

    当你在容器中使用 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)restapi 和来自 restapi 的 angular 访问 restapi。

    我建议您在https://docs.docker.com/compose/阅读更多关于 docker-compose 的信息

    它非常通用且简单,您可以长期使用它,直到您决定构建自己的云;)

    【讨论】:

    • 非常感谢!不幸的是,我只能在明天测试它;会回复您并支持/接受。
    • 由于这是一个 Web 应用程序,它是查看网页的浏览器向其余 api 发出请求,而不是托管 Web 应用程序的容器。在这种情况下,localhost 可以工作,因为浏览器和两个容器都在同一台计算机上运行。除非容器名称是全局可访问的,否则使容器可以按名称访问并不能解决从不同计算机上的浏览器访问 rest-api 的问题。
    • 这里我得到services.restapi.ports contains an invalid type, it should be an array。我也收到Unsupported config option for services.angular: 'name'。有任何想法吗?另外,我是否必须更改 Angular 应用程序中的任何代码,在这种情况下将 export const baseURL = 'http://localhost:3000/'; 更改为 export const baseURL = 'restapi';`?
    • 对于端口错误,而不是 -d "3000:3000" 删除 d 所以它将是 -"3000:3000"。名称应更改为 container_name。 baseURL 需要指向restapi:3000,但要使这一切正常工作,您需要从 form_angular 容器中浏览 Angular 网站
    • @FinnurEiríksson 当我尝试这个并使用docker-compose up 时,我得到Removing form_angular Recreating 2e8227f6fed2_form_angular ... done Recreating c84075454609_form_rest ... done Attaching to form_rest, form_angular form_rest | [2019-02-28 10:49:11 +0000] [9] [INFO] Starting gunicorn 19.9.0 form_rest | [2019-02-28 10:49:11 +0000] [9] [INFO] Listening at: http://0.0.0.0:3000 (9) form_rest | [2019-02-28 10:49:11 +0000] [9] [INFO] Using worker: sync form_rest | [2019-02-28 10:49:11 +0000] [12] [INFO] Booting worker with pid: 12 前端可用,rest api 不起作用。
    猜你喜欢
    • 2020-01-13
    • 2020-03-07
    • 1970-01-01
    • 2020-06-04
    • 2021-11-26
    • 1970-01-01
    • 2016-10-06
    • 2016-07-02
    • 2017-09-23
    相关资源
    最近更新 更多