前端部署三: 基于nginx镜像部署及学习

基于 nginx 镜像构建容器

正如上一篇章所言,对于仅仅提供静态资源服务的前端,实际上是不必将 nodejs 作为运行环境的。

在实际生产经验中,一般选择体积更小,性能更好,基于 nginx 的镜像。

我们通过 docker images 查看镜像体积,发现 node:alpine 体积是 nginx:alpine 的数倍大小。

$ docker images nginx
REPOSITORY   TAG       IMAGE ID       CREATED        SIZE
nginx        alpine    b46db85084b8   6 months ago   23.2MB
 
$ docker images node
REPOSITORY   TAG         IMAGE ID       CREATED        SIZE
node         alpine      025c3cbb849f   4 months ago   169MB

PS: 本项目以 simple-deploy 仓库作为实践,配置文件位于 nginx.Dockerfile

nginx 镜像

在传统方式中,我们一般通过 Linux 服务器来学习如何使用 nginx 进行部署。但是,学习 nginx 的成本太高,需要额外购买一台服务器,不够方便。

也许有人会提出反对意见: 在个人电脑上也可以部署 nginx。

确实是这样,但是 nginx 一般部署在 linux 服务器,很少有人的电脑是 linux 系统,而且即便在 mac 中,其环境和 linux 环境也有很大的不同。

那我们完全可以在本地通过 docker 来简单学习下 nginx。如此,既学习了 docker,又实践了 nginx。

如果你初学 nginx,强烈建议使用 docker 进行学习。本篇文章最后会附上如何启动 nginx 镜像用以学习。

通过以下一行命令可进入 nginx 的环境当中,并且了解 nginx 的目录配置,该命令将在以下章节用到

$ docker run -it --rm nginx:alpine sh
 
# 进入容器中,在容器中可通过 exit 退出容器环境
$ exit

通过以下一行命令可直接访问 nginx 的默认页面

# -p 3000:80,在本地 3000 端口访问 nginx 页面
$ docker run -it --rm -p 3000:80 nginx:alpine
/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
/docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
/docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
/docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
/docker-entrypoint.sh: Configuration complete; ready for start up
2022/01/01 09:12:25 [notice] 1#1: using the "epoll" event method
2022/01/01 09:12:25 [notice] 1#1: nginx/1.21.4
2022/01/01 09:12:25 [notice] 1#1: built by gcc 10.3.1 20210424 (Alpine 10.3.1_git20210424) 
2022/01/01 09:12:25 [notice] 1#1: OS: Linux 5.10.47-linuxkit
2022/01/01 09:12:25 [notice] 1#1: getrlimit(RLIMIT_NOFILE): 1048576:1048576
2022/01/01 09:12:25 [notice] 1#1: start worker processes
2022/01/01 09:12:25 [notice] 1#1: start worker process 34
2022/01/01 09:12:25 [notice] 1#1: start worker process 35
2022/01/01 09:12:25 [notice] 1#1: start worker process 36
2022/01/01 09:12:25 [notice] 1#1: start worker process 37
2022/01/01 09:12:25 [notice] 1#1: start worker process 38
2022/01/01 09:12:25 [notice] 1#1: start worker process 39
 

嗯,熟悉的界面。

简单了解 nginx

以下所有命令均在基于 nginx 的容器中进行,可通过 docker run -it --rm nginx:alpine sh 命令进入容器环境中。

默认配置文件位于 /etc/nginx/conf.d/default.conf,通过 cat 可查看配置。

# 该命令在 nginx 的容器中执行
$ cat /etc/nginx/conf.d/default.conf

把所有注释都删掉,默认配置为以下文件:

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

该配置文件做了以下两个事情。

  1. 监听本地 80 端口
  2. /usr/share/nginx/html 目录做静态资源服务

那我们将我们的示例资源添加到镜像中的 /usr/share/nginx/html 岂不可以正确部署了?

那我们将我们的配置文件添加到镜像中的 /etc/nginx/conf.d/default.conf 岂不可以学习 nginx 的一些指令了。

正是如此。

构建镜像、运行容器

写一个 Dockerfile 将我们的示例项目跑起来,仅仅需要两行代码。由于 nginx 镜像会默认将 80 端口暴露出来,因此我们无需再暴露端口。

PS: 该 Dockerfile 配置位于 simple-deploy/nginx.Dockerfile

FROM nginx:alpine
 
ADD index.html /usr/share/nginx/html/

继续完成 docker-compose.yaml,并创建容器。

version: "3"
services:
  nginx-app:
    build: .
    ports:
      - 4000:80
$ docker-compose up --build

此时,访问 http://localhost:4000 即可访问成功。在控制台查看响应头,可发现有: Server: nginx/1.21.4

基于 node/nginx 镜像体积对比

通过 docker-compose 同时将基于 node/nginx 镜像构建容器,配置文件如下。

PS: 该 docker compose 配置位于 simple-deploy/docker-composey.yaml

version: "3"
services:
  node-app:
    build:
      context: .
      dockerfile: node.Dockerfile
    ports:
      - 3000:3000
  nginx-app:
    build:
      context: .
      dockerfile: nginx.Dockerfile
    ports:
      - 4000:80

通过 docker-compose images 命令,可查看该配置文件的所有镜像体积。此时发现基于 nginx 的镜像为 23.2 MB,而基于 node 的镜像为 133MB (还记得上篇文章的数据吗)。

$ docker-compose images
        Container                 Repository           Tag       Image Id      Size
-------------------------------------------------------------------------------------
simple-deploy_nginx-app_1   simple-deploy_nginx-app   latest   62f362825a0a   23.2 MB
simple-deploy_node-app_1    simple-deploy_node-app    latest   14054cb0f1d8   133 MB

通过 Docker 学习 Nginx 配置

最后,推荐一种高效学习 nginx 的方法: 在本地使用 nginx 镜像并挂载 nginx 配置启动容器

Learning Nginx

无需 Linux 环境,也无需自购个人服务器,你可以通过该方法快速掌握以下 nginx 的常用配置。

  1. 如何配置静态资源缓存策略
  2. 如何配置 CORS
  3. 如何配置 gzip/brotli 配置
  4. 如何配置路由匹配 Location
  5. 如何配置 Rewrite、Redirect 等

我们将注意力集中在静态资源nginx配置两个点,在本地进行更新及维护,并通过 Volume 的方式挂载到 nginx 容器中。

配置文件如下,通过此配置可在 Docker 环境中学习 nginx 的各种指令。

PS: docker-compose 配置文件位于 simple-deploy 中,可通过它实践 nginx 的配置

version: "3"
services:
  learn-nginx:
    image: nginx:alpine
    ports:
      - 4000:80
    volumes:
      - ./nginx.conf:/etc/nginx/conf.d/default.conf
      - .:/usr/share/nginx/html

通过 docker-compose 启动该容器,如果需要修改配置,验证配置是否生效,可通过 docker-compose 重新启动该容器。

$ docker-compose -f learn-nginx.docker-compose.yaml up learn-nginx

作业

  1. 基于 nginx 镜像将极简前端项目进行部署
  2. 我们的基础镜像 tag 总是携带 alpine,它是什么

小结

通过本篇文章,已基于 nginx 镜像成功部署前端,镜像体积也由 133MB 下降到 23.2MB。并且了解了如何基于 nginx 镜像来更好地学习 nginx 配置部署知识。

然而此三篇文章仅仅部署了一个 hello 版的页面。

下一篇文章以 create-react-app 为例,部署一个复杂的单页应用,与业务项目完全一致。