惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

The GitHub Blog
The GitHub Blog
I
InfoQ
U
Unit 42
WordPress大学
WordPress大学
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Apple Machine Learning Research
Apple Machine Learning Research
J
Java Code Geeks
月光博客
月光博客
D
Docker
Stack Overflow Blog
Stack Overflow Blog
D
DataBreaches.Net
阮一峰的网络日志
阮一峰的网络日志
Blog — PlanetScale
Blog — PlanetScale
V
Visual Studio Blog
博客园 - 聂微东
A
About on SuperTechFans
腾讯CDC
Jina AI
Jina AI
Microsoft Azure Blog
Microsoft Azure Blog
GbyAI
GbyAI
博客园 - 【当耐特】
罗磊的独立博客
博客园 - 三生石上(FineUI控件)
M
MIT News - Artificial intelligence

ALBERTAZ

How I Built a Scannable 3D QR Code Generator | Every QR Code OpenStreetMap Data Pipeline for Canvas Maps | EveryCityMap 每日关灯:今天这题理论最少 8 步 OpenStreetMap + Canvas 城市地图实践:EveryCityMap 的五个工程取舍 OpenStreetMap + Canvas 城市地图实践:EveryCityMap 的五个工程取舍 博客 CDN 迁移到 Cloudflare R2 博客 CDN 迁移到 Cloudflare R2 Migrate my website to SvelteKit2 Migrate my website to SvelteKit2 漫谈编辑器 漫谈编辑器 Pure ESM package Pure ESM package 又折腾博客了 又折腾博客了 Rewrite my website with Svelte Rewrite my website with Svelte 字体漫谈-网站字体最佳实践 字体漫谈-网站字体最佳实践 你不知道的 Web Components - 现状 你不知道的 Web Components - 现状 你不知道的 Web Components - 过去和未来 你不知道的 Web Components - 过去和未来 Node 应用本地 HTTPS Node 应用本地 HTTPS docker 部署 Gatsby 应用 再提示『您的磁盘几乎已满』算我输 再提示『您的磁盘几乎已满』算我输 G6-Mobile 的前世今生 G6-Mobile 的前世今生
docker 部署 Gatsby 应用
https://www.albertaz.com/about · 2021-05-23 · via ALBERTAZ

用 Gatsby 重构自己的博客之后,他的众多优点比如可以用 react 组件化开发,可以享受 ssr、单页应用也能 seo 等等,感觉一直很爽。 但随着 Gatsby 和它的相关插件同步升级,下载、构建失败的事情经常爆出,每一个都是时间杀手,解决一次可能要花掉一个晚上。主要是跟图片相关的几个插件 gatsby-transformer-sharp ,需要同构c构建的模块,国内网络经常下载失败。

gatsby-plugin-sharp,依赖pngquant-bin ,这个包下载也会经常出问题 pngquant-bin@5.0.1 postinstall: node lib/install.js · Issue #97 · imagemin/pngquant-bin · GitHubpngquant-bin@5.0.2 postinstall · Issue #104 · imagemin/pngquant-bin · GitHub gatsby-image,依赖 mozjpg ,mozjpeg 的编译需要 libtool automake autoconf nasm。

最近出现的的构建图片出错 construct-error.js - child “error” fails because “error” must be an object · Issue #15242 · gatsbyjs/gatsby · GitHub

而这个 issue 依然没有 close: gatsby-plugin-sharp: WorkerError @2.6.27 · Issue #26723 · gatsbyjs/gatsby · GitHub ,试了各种 hack 方法没法解决,我只好将版本回滚并锁定。

问题是如果还有其他服务也做了依赖升级导致依赖冲突怎么办?如果以后我重装系统、更换云服务器,岂不是还要重走一遍下载安装构建的坑?万一倒时候又有新坑怎么办? 因此我开始着手把 Gatsby 项目 docker 化,做成镜像传到 docker hub。即便以后换个运行环境也可以快速使用,不用再被时间杀手折磨。

准备工作

制作项目镜像

gatsby 的 docker 镜像有两个 tag 版本:

  1. latest - 会起一个nginx serve 静态文件,需要手动把 public 目录拷过去
  2. onbuild - 构建并生成一个新的docker镜像

这里直接用 onbuild 版本的镜像,新建 dockerfile.dockerignore

Shell Session
touch Dockerfile .dockerignore

dockerfile 中添加:

Shell Session
FROM gatsbyjs/gatsby:onbuild

.dockerignore 中添加:

Shell Session
.cache/
node_modules/
# 不要添加 public/

这里没有参考 gatsby 镜像的文档添加 public/  ,因为接下来会将 gatsby 网站项目打包构建出静态资源,/public 目录即为其静态资源目录:

Shell Session
gatsby build

接下来创建镜像:

Shell Session
docker build -t albertaz.com:latest .

这里用 -t 打上了 latest 标签, albertaz.com 是我的镜像名。由于我在 dockerfile 同级目录创建镜像,所以最后的 . 不能省略。

整个镜像制作时间大概会持续两道三分钟,时间很快,主要原因在于 gatsby 自身的 docker 镜像使用了一个轻型的 linux 系统发行版 alpine ,整个体积极小只有 4.4 M,而我生成的网站项目镜像也只有 13 M。

Shell Session
➜  my-blog docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
albertaz.com        latest              ba541dad4832        3 minutes ago       14.2MB

接下来运行着这个镜像试试看:

Shell Session
docker run --rm -p 80:80 albertaz.com

镜像运行会创建一个 container,--rm 表示在 container 停止后自动清除, -p 80:80 表示把本地机器的 80 端口映射到 container 的 80 端口(也是 container 的默认端口),所以接下来可以通过浏览器打开 localhost 访问网站了。

优化镜像配置

前面提到 gatsby 镜像会在运行时起一个 nginx serve 静态文件,其实是因为镜像里也安装了一个 nginx。镜像文档里还提到了通过两种方式修改 nginx 配置: 一种是修改 Dockerfile, 使用自定义的 nginx 配置文件:

Bash
FROM gatsbyjs/gatsby:latest
COPY nginx-server-rules.conf /etc/nginx/server.conf

另一种是通过 docker run 命令 的 --env-file  传参:

Bash
docker run --rm -e CACHE_IGNORE=html -p 80:80 albertaz.com

但如果我需要加多个参数,配置更多端口、网络、启动策略等等,这个命令会越写越长,显然用一个脚本文件写这些指令会更好。不过当我在 mac 上装 docker desktop 的时候,它自带了 docker-compose,docker-compose 的意义是让我们可以编排多个 容器、不用写复杂的 shell 脚本。现在尽管只有一个容器,但依然可以借助 docker-compose,通过 yaml 配置文件的方式来运行,这个方式显然更有拓展性。

在项目根目录下创建一个 docker-compose.yml 文件:

Bash
version: "3.8"
services:
  albertaz.com:
    image: albertaz.com
    environment:
      - CACHE_IGNORE=html
    ports:
      - "80:80"

可以看到写法更有结构性、更易读。随后就可以通过 docker-compose 运行镜像:

Bash
## 启动
docker-compose up -d

## 停止
docker-compose down

docker-compose 在停止运行时会自动清除 container,不用像 docker run 那样加 —rm 参数。

部署

上传到 docker hub

本地自测没问题之后,开始把创建好的镜像上传到 docker hub,当然前提是需要注册一下账号,拿到一个 docker hub 的用户名。 上传前先把本地镜像通过 docker tag  关联到 docker hub

Bash
docker tag albertaz.com:latest albertaz/albertaz.com:latest

albertaz/albertaz.com:latest 中第一个 albertaz 就是 docker hub 的用户名。 随后上传:

Bash
docker push albertaz/albertaz.com

服务器运行镜像

上传完成后,回到服务器,装好 docker 和 docker-compose。因为我依然想用 docker-compose 运行镜像,所以需要再把 docker-compose.yml 文件也上传到服务器,这个文件之前可不会被 push 到 docker hub。随后启动镜像:

Bash
docker-compose up -d

服务器会从 docker hub 拉取我们配置好的网站镜像,不用再跑一遍安装构建流程了。

更新镜像

另外如果我网站更新了,需要更新镜像文件,利用 docker-compose 做法很简单,直接在启动命令后加上 container 名即可:

Bash
docker-compose up -d albertaz.com

注意更新的时候原来的 container 大概率是在运行的,docker-compose 可以让 container 基于新的镜像运行,无需停止原来正在运行的 container。但如果直接通过 docker 原生命令运行,就需要先 docker container stop 停止 container,重新 docker run ,所以网站更新时会有一段无法访问的时间。这点也是选择用 docker-compose 的重要原因之一。