问题:通过 NGINX 在 Docker 中服务 Angular 10 应用程序

我正在尝试使用 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 日志应该被重定向到控制台,从而显示在容器的终端中。

3.这里的肉在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,保存在Dockerfile的同一文件夹中):

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

(我还发现这个其他帖子,但对于 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 端口)。

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

我在 logs 中查找了一些内容,但docker logs mycontainer什么也没显示。

我试图检查容器的 filesystem 以查看 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替换了我的nginx.conf,重建了应用程序并运行它。这次构建花费了大约 15 分钟,并向 Docker 守护进程发送了 1.134 GB 的构建上下文。

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

  • 图片:vedph2020/cadmus_web:1.0.5(1.0.4是我的 nginx 的那个)。只需在此处使用docker-compose.yml,标签1.0.5用于cadmus-web服务。那里有一些后端的东西,但我确信它可以工作,因为我可以在 localhost:60380/swagger 连接到它的端点。

  • 存储库: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访问我的,但没有运气:同样的欢迎页面。

解答

我想我找到了问题:通过查看文件系统转储,我注意到了default.conf文件;检查它的内容,我看到在 80 端口已经有一个localhost的位置。我在想这应该不是问题,因为我的nginx.conf文件没有导入(include指令)它;但似乎它仍然得到评估。至少,一旦我在我的 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)......

Logo

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

更多推荐