【问题标题】:Serving Angular 10 app in Docker via NGINX通过 NGINX 在 Docker 中提供 Angular 10 应用程序
【发布时间】:2021-01-13 12:54:27
【问题描述】:

我正在尝试使用 NGINX 在 Docker 中部署一个 Angular 10 Web 应用程序,但我无法让它为其提供服务。谷歌搜索我发现了很多稀疏的信息,但我想出了这个程序:

  1. 通常构建 Angular 应用 用于生产 (--prod),在 Docker 之外。结果将保存到项目的dist 文件夹中,然后将其复制到容器中。我发现了其他在容器内使用多阶段构建的示例;但出于可扩展性目的,不鼓励这样做。无论如何,手动构建应用程序让我更容易控制结果,所以对我来说这是要走的路。

  2. 使用nginx:alpine 提供一个Dockerfile,我只需将自定义配置和我编译的应用程序复制到容器中,然后通过ENTRYPOINT 将其作为可执行文件运行:

FROM nginx:alpine

COPY nginx.conf /etc/nginx/nginx.conf

WORKDIR /usr/share/nginx/html
COPY dist/myapp/ .

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

这样,NGINX 日志应该被重定向到控制台,从而显示在容器的终端中。

  1. 这里的重点是在 NGINX 配置 文件中。我对此了解不多,但根据https://blog.codecentric.de/en/2019/03/docker-angular-dockerize-app-easily/ 和https://denys.dev/2018-03-02/your-angular-apps-as-docker-containers/ 的证据,我想出了这个,它应该正确考虑HTML 5 路由(nginx.conf,保存在@的同一文件夹中987654334@):
worker_processes  1;

events {
    worker_connections  1024;
}

http {
    server {
        listen 80;
        server_name  localhost;

        root   /usr/share/nginx/html;
        index  index.html index.htm;
        include /etc/nginx/mime.types;

        gzip on;
        gzip_min_length 1000;
        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;

        location / {
            try_files $uri $uri/ /index.html;
        }
    }
}

(我也发现了这个other post,但对于 Angular 而言,它的配置不太完整)。

  1. 构建图像 (docker build . -t myrepo/myapp:tag)。这样做时,在dist 文件夹之外发送无用内容需要花费大量时间。因此,根据https://denys.dev/2018-03-02/your-angular-apps-as-docker-containers/(“优化构建”)的提示,我添加了一个 .dockerignore :
e2e
node_modules
src

这一次,构建速度要快得多。在这两种情况下,它都已成功构建。

我现在可以直接运行容器 (docker run -d -p 4200:80 myrepo/myapp:tag) 或从 docker compose 脚本。在这两种情况下,我都需要将容器的端口 80 (NGINX) 重定向到主机端口 4200(通常的 Angular 应用程序 localhost 端口)。

问题:我希望看到我的应用程序由 NGINX 在localhost:4200 提供服务。相反,我发现的只是默认的 NGINX 欢迎页面,告诉我 NGINX 服务器已成功安装并工作,但需要进一步配置。

我在日志中寻找了一些东西,但docker logs mycontainer 什么也没显示。

我尝试检查容器的 文件系统 以查看 Angular 应用程序是否在其位置 (usr/share/nginx/html)。为此,我遵循Exploring Docker container's file system 的建议:对于 alpine 映像,没有 bash,因此我将文件系统转储到带有 docker export mycontainer > mydump.tar 的 TAR 文件中。通过查看 TAR 的内容,我可以看到我的应用文件在那里:index.html、JS 文件、资产等。

我在这里缺少什么来完成 NGINX 配置并提供我的应用程序?

更新

我按照@Derek 的指示:删除了.gitignore,用建议的替换了我的nginx.conf,重建了应用程序,然后运行它。这次构建花费了大约 15 分钟,并向 Docker 守护进程发送了 1.134 GB 的构建上下文。

为了在我的测试机器上快速运行它,我在 Docker Hub 中发布了图像。整个项目是开源的,所以如果有人想在重现环境中诊断某些东西,那么二进制图像及其源代码都有:

  • 图片:vedph2020/cadmus_web:1.0.5(1.0.4 是我的 nginx 的那个)。只需在此处使用docker-compose.yml,并在cadmus-web 服务中使用标签1.0.5。那里有一些后端的东西,但我确信它可以工作,因为我可以在 localhost:60380/swagger 连接到它的端点。
  • repository:https://github.com/vedph/cadmus_web(真正的应用名称是cadmus_web;因此构建是docker build . -t vedph2020/cadmus_web:1.0.5)。

同时,我尝试创建一个空的虚拟 Angular 应用程序,并使用我原来的 Dockerfile 和 nginx 文件。令我惊讶的是,它奏效了。唯一的区别是虚拟 Angular 应用程序没有路由,而我的具有 hash location 策略。假设 NGINX 中有一些与哈希相关的配置问题,我尝试从 http://localhost:4200/#/home 访问我的,但没有运气:同样的欢迎页面。

【问题讨论】:

  • for the alpine image there is no bash Alpine 应该有/bin/sh,它会让你完成同样的事情。你能检查/usr/share/nginx/html/index.html 是否包含你的代码吗?
  • 谢谢,那个alpine好像没有bash,只是一个扣,没时间查。无论如何,除了export,引用的 SO 帖子中列出的方法都不起作用。我的index.html 包含预期的代码,据我从 TAR 中可以看到。

标签: angular docker nginx


【解决方案1】:

我告诉你我是如何做我的容器的...我看到一切都是一样的,但是请删除 .dockerignore...当您只复制 dist 文件时,您不需要忽略 src...等。 .

重要

  1. 在运行 ng build.... 时验证您的应用程序的名称。 文件夹并查看文件夹的名称以验证它是我的应用程序

结构

这需要在您的应用程序的根目录中

src
dist
    name_of_your_app
        index.html //and the other files
e2e
node_modules
nginx.conf
Dockerfile

DOCKERFILE

FROM nginx:alpine
COPY nginx.conf /etc/nginx/nginx.conf
COPY dist/name_of_your_app/ /usr/share/nginx/html
EXPOSE 80

NGINX 配置

user  nginx;
worker_processes  auto;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;

    keepalive_timeout  65;

    server {
        listen       80;
        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;
        }
    }
}

构建

docker build -t my_app .

运行

docker run -d -p 4200:80 -t my_app

仅此而已...也许是某些配置,标签... dockerignore 这是您的问题。告诉我这是否能解决您的问题。

【讨论】:

  • 非常感谢德里克!我听从了你的指示,但不幸的是它没有用。请查看我更新帖子的底部。
  • 你解决了就好了,这个具体案例大家学习了
  • 抱歉,您的建议无效。幸运的是,我似乎找到了问题所在,现在发布答案。
  • 这就是我的意思,即使我的不起作用,你也找到了答案。
【解决方案2】:

我想我找到了问题所在:通过查看文件系统转储,我注意到了default.conf 文件;检查它的内容,我看到在端口 80 上已经有一个localhost 的位置。我认为这应该不是问题,因为我的nginx.conf 文件没有 导入(@987654324 @指令)它;但似乎它仍然得到评估。至少,一旦我在我的 Dockerfile 中删除它:

FROM nginx:alpine
COPY nginx.conf /etc/nginx/nginx.conf
RUN rm /etc/nginx/conf.d/default.conf
WORKDIR /usr/share/nginx/html
COPY dist/apps/cadmus/ .
EXPOSE 80

应用程序现已按预期启动。希望这可以帮助像我这样的新手,定义一个清晰的 Angular 服务程序(我想无论如何我都可以重新引入 gzip 指令,甚至是 .dockerignore)...

【讨论】:

    猜你喜欢
    • 2019-09-22
    • 2021-02-04
    • 1970-01-01
    • 1970-01-01
    • 2020-10-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-21
    相关资源
    最近更新 更多