Add the compose file
It runs the same image with the settings a service that stays up wants: it restarts unless stopped, mounts the filesystem read-only because the service writes nothing, drops the ability to gain privileges, and probes the service every thirty seconds. The probe is written against the shell rather than against a tool, because the image carries no HTTP client. It opens the connection as a file descriptor with `bash`, writes the request, and reads the status line back. That was checked against a running service and against a stopped one: it reports healthy in the first case and unhealthy in the second, which is the only thing a probe has to get right. The host port is a variable with a default, because which port a machine has free is a matter of taste, and the build context is the directory above, as the Dockerfile's is.
This commit is contained in:
parent
081c7d9275
commit
6403e50192
18
README.md
18
README.md
|
|
@ -121,7 +121,22 @@ The command names the host explicitly. The program defaults to the loopback
|
||||||
address, where it answers only itself, so a container started without it would
|
address, where it answers only itself, so a container started without it would
|
||||||
serve nothing to anyone.
|
serve nothing to anyone.
|
||||||
|
|
||||||
There is no `HEALTHCHECK`. Probing `GET /health` is what an orchestrator
|
`docker-compose.yml` does the same thing with the settings a long-running
|
||||||
|
service wants: it restarts unless stopped, mounts the filesystem read-only
|
||||||
|
because nothing is written to it, drops the ability to gain privileges, and
|
||||||
|
probes the service every thirty seconds.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cd apsis-book
|
||||||
|
docker compose up --build
|
||||||
|
```
|
||||||
|
|
||||||
|
The probe is written against the shell rather than against a tool, because
|
||||||
|
the image carries no HTTP client: it carries one binary and nothing else, and
|
||||||
|
adding a client for a probe would undo that. `bash` opens the connection,
|
||||||
|
writes the request and reads the status line back.
|
||||||
|
|
||||||
|
There is no `HEALTHCHECK` in the image itself. Probing `GET /health` is what an orchestrator
|
||||||
should do, and a probe inside the container would mean adding an HTTP client
|
should do, and a probe inside the container would mean adding an HTTP client
|
||||||
to an image that needs no other tool. A Kubernetes probe says the same thing
|
to an image that needs no other tool. A Kubernetes probe says the same thing
|
||||||
without one:
|
without one:
|
||||||
|
|
@ -230,6 +245,7 @@ apsis-book/
|
||||||
│ └── concepts/<layer>/ documents, one directory per layer
|
│ └── concepts/<layer>/ documents, one directory per layer
|
||||||
├── Dockerfile the release image, in three stages
|
├── Dockerfile the release image, in three stages
|
||||||
├── Dockerfile.dockerignore what the image build is not sent
|
├── Dockerfile.dockerignore what the image build is not sent
|
||||||
|
├── docker-compose.yml runs the image with the settings it wants
|
||||||
├── frontend/ Svelte and TypeScript, built by Vite
|
├── frontend/ Svelte and TypeScript, built by Vite
|
||||||
│ ├── src/lib/ API client, router, components, formatting
|
│ ├── src/lib/ API client, router, components, formatting
|
||||||
│ ├── src/pages/ one component per route
|
│ ├── src/pages/ one component per route
|
||||||
|
|
|
||||||
15
README.zh.md
15
README.zh.md
|
|
@ -105,7 +105,19 @@ docker run --rm -p 8080:8080 apsis-book:0.1.0
|
||||||
命令中显式给出主机。程序的默认值是回环地址,那里它只回应自己,因此不带这一项启动
|
命令中显式给出主机。程序的默认值是回环地址,那里它只回应自己,因此不带这一项启动
|
||||||
的容器不会向任何人提供服务。
|
的容器不会向任何人提供服务。
|
||||||
|
|
||||||
镜像没有 `HEALTHCHECK`。探测 `GET /health` 是编排系统应当做的事,而在容器内部
|
`docker-compose.yml` 做同样的事,并带上长时间运行的服务所需要的设置:除非被停止
|
||||||
|
否则自动重启,因文件系统不被写入而以只读方式挂载,去掉取得更多权限的能力,并且
|
||||||
|
每三十秒探测一次服务。
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cd apsis-book
|
||||||
|
docker compose up --build
|
||||||
|
```
|
||||||
|
|
||||||
|
该探针用 shell 写成而不是用某个工具,因为镜像不携带 HTTP 客户端:它只携带一个
|
||||||
|
二进制,为探针添加客户端会破坏这一点。`bash` 打开连接、写入请求并读回状态行。
|
||||||
|
|
||||||
|
镜像本身没有 `HEALTHCHECK`。探测 `GET /health` 是编排系统应当做的事,而在容器内部
|
||||||
探测意味着给一个不需要其他工具的体积里加上 HTTP 客户端。Kubernetes 的探针无须
|
探测意味着给一个不需要其他工具的体积里加上 HTTP 客户端。Kubernetes 的探针无须
|
||||||
它即可表达同一件事:
|
它即可表达同一件事:
|
||||||
|
|
||||||
|
|
@ -202,6 +214,7 @@ apsis-book/
|
||||||
│ └── concepts/<layer>/ 文档,每层一个目录
|
│ └── concepts/<layer>/ 文档,每层一个目录
|
||||||
├── Dockerfile 发布镜像,分三个阶段
|
├── Dockerfile 发布镜像,分三个阶段
|
||||||
├── Dockerfile.dockerignore 镜像构建不接收的内容
|
├── Dockerfile.dockerignore 镜像构建不接收的内容
|
||||||
|
├── docker-compose.yml 以长期运行所需的设置来运行镜像
|
||||||
├── frontend/ Svelte 与 TypeScript,由 Vite 构建
|
├── frontend/ Svelte 与 TypeScript,由 Vite 构建
|
||||||
│ ├── src/lib/ API 客户端、路由器、组件、格式化
|
│ ├── src/lib/ API 客户端、路由器、组件、格式化
|
||||||
│ ├── src/pages/ 每个路由一个组件
|
│ ├── src/pages/ 每个路由一个组件
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,87 @@
|
||||||
|
# Running the release image.
|
||||||
|
#
|
||||||
|
# The service keeps nothing between runs: the documents, the graphs, the
|
||||||
|
# interface catalogue and the frontend are all inside the binary, and the
|
||||||
|
# only thing it writes is what it sends. The service is therefore mounted
|
||||||
|
# read-only and can be replaced at any time.
|
||||||
|
#
|
||||||
|
# 运行发布镜像。
|
||||||
|
#
|
||||||
|
# 服务在两次运行之间不保留任何东西:文档、图谱、接口目录与前端都在二进制里,它
|
||||||
|
# 唯一写出的东西就是它发送的内容。因此该服务以只读方式挂载,且可以随时被替换。
|
||||||
|
#
|
||||||
|
# From this directory:
|
||||||
|
#
|
||||||
|
# docker compose up --build
|
||||||
|
#
|
||||||
|
# 在本目录执行上面那条命令。
|
||||||
|
#
|
||||||
|
# The build context is the directory above, because the crate depends on
|
||||||
|
# `apsis-rs` by path. A reader who only wants to run a published image can
|
||||||
|
# drop the `build` section and keep `image`.
|
||||||
|
#
|
||||||
|
# 构建上下文是上一级目录,因为该 crate 以路径依赖引用 `apsis-rs`。如果只想运行
|
||||||
|
# 已发布的镜像,可以删去 `build` 一节而保留 `image`。
|
||||||
|
|
||||||
|
name: apsis-book
|
||||||
|
|
||||||
|
services:
|
||||||
|
apsis-book:
|
||||||
|
build:
|
||||||
|
context: ..
|
||||||
|
dockerfile: apsis-book/Dockerfile
|
||||||
|
image: apsis-book:0.1.0
|
||||||
|
|
||||||
|
# The container listens on 8080 and the host side is a matter of taste,
|
||||||
|
# so it is a variable with a default rather than a constant.
|
||||||
|
#
|
||||||
|
# 容器监听 8080,而宿主机一侧是个人偏好,因此它是一个带默认值的变量而不是
|
||||||
|
# 常量。
|
||||||
|
ports:
|
||||||
|
- "${APSIS_BOOK_PORT:-8080}:8080"
|
||||||
|
|
||||||
|
# A documentation service has no reason to stop, and a machine that
|
||||||
|
# restarts should bring it back.
|
||||||
|
#
|
||||||
|
# 文档服务没有理由停止,而重启的机器应当把它带回来。
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
# The filesystem is not written to, so it is mounted read-only, and the
|
||||||
|
# process runs as `nobody` with no way to gain more than it has.
|
||||||
|
#
|
||||||
|
# 文件系统不被写入,因此以只读方式挂载;进程以 `nobody` 运行,且无法取得超出
|
||||||
|
# 自身已有的权限。
|
||||||
|
read_only: true
|
||||||
|
security_opt:
|
||||||
|
- no-new-privileges:true
|
||||||
|
|
||||||
|
# The probe is written against the shell rather than against a tool,
|
||||||
|
# because the image carries no HTTP client: it carries one binary and
|
||||||
|
# nothing else, and adding a client for a probe would undo that.
|
||||||
|
#
|
||||||
|
# 该探针用 shell 写成而不是用某个工具,因为镜像不携带 HTTP 客户端:它只携带
|
||||||
|
# 一个二进制,为探针添加客户端会破坏这一点。
|
||||||
|
#
|
||||||
|
# `bash` opens the connection as a file descriptor, the request is written
|
||||||
|
# to it, and the status line is read back.
|
||||||
|
#
|
||||||
|
# `bash` 把连接打开为一个文件描述符,请求写入其中,状态行从中读回。
|
||||||
|
healthcheck:
|
||||||
|
test:
|
||||||
|
- CMD-SHELL
|
||||||
|
- >-
|
||||||
|
exec 3<>/dev/tcp/127.0.0.1/8080 || exit 1;
|
||||||
|
printf 'GET /health HTTP/1.0\r\n\r\n' >&3;
|
||||||
|
grep -q '200 OK' <&3
|
||||||
|
interval: 30s
|
||||||
|
timeout: 5s
|
||||||
|
# Three failures in a row, which is ninety seconds of a service that is
|
||||||
|
# not answering, before the container is called unhealthy.
|
||||||
|
#
|
||||||
|
# 连续三次失败,即服务九十秒没有回应,才把容器判为不健康。
|
||||||
|
retries: 3
|
||||||
|
# The content is parsed at startup and is small, so the service is
|
||||||
|
# listening within the first second.
|
||||||
|
#
|
||||||
|
# 内容在启动时解析且体量很小,因此服务在第一秒内就已监听。
|
||||||
|
start_period: 5s
|
||||||
Loading…
Reference in New Issue