前言
接 《Docker 的总结与使用之Docker(一)》 。
说明
一般情况下,我们可以使用 Dockerfile 来进行镜像的构建。流程是这样的:
- 获取到基础镜像
- 编写一个 Dockerfile 文件
- 使用 docker build 命令进行构建
使用
指令介绍
指令 |
说明 |
FROM |
基础镜像,从哪个镜像开始构建 |
MAINTAINER |
作者信息,弃用 |
LABEL |
镜像元信息,KV 形式,比如作者信息 |
COPY |
从宿主机复制文件到镜像里 |
ADD |
从宿主机复制文件到镜像里,区别于 COPY 会对 tar 包解压 |
WORKDIR |
设置工作目录,相当于执行 CD |
ENV |
设置镜像里的环境变量 |
ARG |
构建过程指定的环境变量 |
USER |
启动容器的用户 |
RUN |
构建镜像时执行的命令,一般执行安装环境相关的命令 |
CMD |
容器启动后的执行的命令,可被 docker run 覆盖 |
ENTRYPOINT |
容器启动后默认运行程序或命令,不可被 docker run 覆盖 |
EXPOSE |
暴露容器里的端口 |
VOLUME |
将宿主机的目录挂载到容器里,为了低耦合,一般不用 |
ONBUILD |
触发器,当该镜像被用作另一个构建过程的基础时 |
STOPSIGNAL |
发送给容器以退出的系统调用信号 |
HEALTHCHECK |
周期性检查容器健康状态的命令 |
SHELL |
覆盖 Docker 中默认的 shell |
单阶段构建
说明
单阶段构建是指整个构建过程只需要在一个基础镜像上构建就可以完成。
构建 Vue 相关镜像示例
- 创建演示项目
1
2
|
pnpm create vite@latest demo
cd demo
|
- 获取基础镜像
1
|
$ docker pull node:16.18.0
|
- 编写 Dockerfile 文件
1
2
3
4
5
6
7
8
9
10
|
$ vim ./Dockerfile
FROM node:16.18.0
LABEL author=hwsdien
WORKDIR /www
COPY . .
RUN npm config set registry http://mirrors.cloud.tencent.com/npm/
RUN npm install -g pnpm@next-7
RUN pnpm install
EXPOSE 5173
CMD ["pnpm", "dev", "--host", "0.0.0.0"]
|
- 执行 build
1
|
$ docker build -t hwsdien/yhz-vue:v1.0.0 .
|
- 运行 & 测试
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
$ docker run -tid --name test-vue -p 8080:5173 hwsdien/yhz-vue:v1.0.0
$ curl http://127.0.0.1:8080
<!doctype html>
<html lang="en">
<head>
<script type="module" src="/@vite/client"></script>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + Vue + TS</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>
|
构建 Golang 相关镜像示例
- 创建演示项目
这里使用 echo 框架进行演示,创建 go 项目
创建 main.go 文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
package main
import (
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v4/middleware"
"net/http"
)
func main() {
// Echo instance
e := echo.New()
// Middleware
e.Use(middleware.Logger())
e.Use(middleware.Recover())
// Routes
e.GET("/", hello)
// Start server
e.Logger.Fatal(e.Start(":1323"))
}
// Handler
func hello(c echo.Context) error {
return c.String(http.StatusOK, "Hello, World!")
}
|
- 获取基础镜像
1
|
$ docker pull golang:1.22.0-alpine
|
- 编写 Dockerfile 文件
1
2
3
4
5
6
7
8
9
10
11
|
$ vim ./Dockerfile
FROM golang:1.22.0-alpine
LABEL author="hwsdien"
WORKDIR /www
COPY . .
RUN go env -w GO111MODULE=on
RUN go env -w GOPROXY=https://goproxy.cn,direct
RUN go mod download
RUN CGO_ENABLED=0 GOOS=linux go build -o demo
EXPOSE 1323
CMD ["./demo"]
|
- 执行 build
1
|
$ docker build -t hwsdien/yhz-golang:v1.0.0 .
|
- 运行 & 测试
1
2
3
|
$ docker run -tid --name test-golang -p 8088:1323 hwsdien/yhz-golang:v1.0.0
$ curl http://127.0.0.1:8088
|
构建 Python 相关镜像示例
- 创建演示项目
这里使用 fastapi 进行演示,创建 main.py 文件,内容如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
from typing import Union
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def read_root():
return {"Hello": "World"}
@app.get("/items/{item_id}")
def read_item(item_id: int, q: Union[str, None] = None):
return {"item_id": item_id, "q": q}
|
- 获取基础镜像
1
2
3
4
5
6
7
|
$ docker pull python:3.12.2-alpine
# 尽量使用 alpine 版本,因为空间占用极少
# 这里可以看到非 alpine 版本有 1G 多
$ docker images | grep python
python 3.12.2 d8be44680b2e 3 weeks ago 1.02GB
python 3.12.2-alpine 80f904359cf6 3 weeks ago 56.5MB
|
- 编写 Dockerfile 文件
1
2
3
4
5
6
7
8
9
|
$ vim ./Dockerfile
FROM python:3.12.2-alpine
LABEL author=hwsdien
WORKDIR /www
COPY . .
RUN pip install fastapi -i https://pypi.tuna.tsinghua.edu.cn/simple
RUN pip install "uvicorn[standard]" -i https://pypi.tuna.tsinghua.edu.cn/simple
EXPOSE 8000
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--reload"]
|
- 执行 build
1
|
$ docker build -t hwsdien/yhz-python:v1.0.0 .
|
- 运行 & 测试
1
2
3
|
$ docker run -tid --name test-python -p 8081:8000 hwsdien/yhz-python:v1.0.0
$ curl http://127.0.0.1:8081
|
多阶段构建
说明
多阶段是指整个构建过程需要依赖多个基础镜像,每个阶段需要依赖上个阶段构建的产物,比如某个java项目,第一个阶段构建打包 jar 文件,第二个阶段运行第一个阶段的 jar 文件。
构建 Nginx + Vue 镜像
- 创建演示项目
1
2
|
pnpm create vite@latest demo
cd demo
|
- 获取基础镜像
1
2
|
$ docker pull node:16.18.0
$ docker pull nginx:latest
|
- 编写 Nginx 的配置文件(nginx.conf)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
$ cat ./nginx.conf
user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;
events {
worker_connections 768;
}
http {
sendfile on;
tcp_nopush on;
types_hash_max_size 2048;
include /etc/nginx/mime.types;
default_type application/octet-stream;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE
ssl_prefer_server_ciphers on;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
gzip on;
server {
listen 80;
server_name localhost;
location / {
root /www;
index index.html;
try_files $uri $uri/ /index.html;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /www;
}
}
}
|
- 编写 Dockerfile 文件
1
2
3
4
5
6
7
8
9
10
11
12
13
|
$ vim ./Dockerfile
FROM node:16.18.0
LABEL author="hwsdien"
WORKDIR /app
COPY . .
RUN npm config set registry http://mirrors.cloud.tencent.com/npm/
RUN npm install -g pnpm@next-7
RUN pnpm install & pnpm build
FROM nginx:latest
RUN mkdir /www
COPY --from=0 /app/dist /www
COPY nginx.conf /etc/nginx/conf.d/www.conf
|
- 执行 build
1
|
$ docker build -t hwsdien/yhz-nginx-vue:v1.0.0 .
|
- 运行 & 测试
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
$ docker run -tid --name test-nginx -p 8082:80 hwsdien/yhz-nginx-vue:v1.0.0
$ curl http://127.0.0.1:8082
<!doctype html>
<html lang="en">
<head>
<script type="module" src="/@vite/client"></script>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + Vue + TS</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>
|