Docker容器实战笔记
Docker
Docker 是 dotCloud 公司 2013年开源的一个基于 LXC 的高级容器引擎,基于Go语言开发并遵循Apache2.0协议。
容器完全使用沙箱机制,相互之间不会有任何接口,更重要的是容器的性能开销极低。Docker 可以使开发者打包他们的应用以及依赖到一个轻量级、可移植的容器中,然后发布到任何其他机器上。
Docker官方文档:https://docs.docker.com
Docker Hub:https://hub.docker.com
架构
Docker 使用 CS(客户端-服务器)架构。
Docker 客户端与Docker 守护进程进行通信,守护进程完成构建、运行和分发Docker容器繁重的工作。
Docker 客户端与守护进程可以在同一个系统上运行,也可以在不同的系统上进行远程通信。
Docker 客户端与Docker 守护进程在网络接口上使用REST API进行通信。
基本概念
Docker基本概念:
- 客户端
- 守护进程
- 仓库(Registry)
- 镜像(Image)
- 容器(Container)
客户端
Docker客户端是用户与Docker交互的主要方式,它是一个命令行界面(CLI)。
守护进程
Docker守护进程(Demand)监听Docker API请求并管理Docker对象:镜像、容器、网络、卷。

仓库
仓库用于存储Docker镜像,Docker Hub 是公共仓库,也可以构建自己的私服仓库。
底层技术
Docker使用Go语言开发,并参考了Linux内核的多个功能来实现。
Linux发行版
通过以下几种方式,可快速准确识别容器底层发行版:
- 优先执行:
docker exec -it <容器名> cat /etc/os-release
- 快速判断:观察包管理器(apt/yum/apk)
- 深度验证:进入容器 Shell 手动检查
# Debian/Ubuntu(使用 apt)
docker exec -it <容器名> which apt
# RHEL/CentOS(使用 yum/dnf)
docker exec -it <容器名> which yum
# Alpine(使用 apk)
docker exec -it <容器名> which apk
# 查看Linux 发行版的几种方式:
cat /etc/issue
cat /proc/version
lsb_release -a
cat /etc/os-release # 通常查看容器
镜像仓库
国内拉取docker官方镜像,有时会有网络问题,或者速度很慢,国内优先使用国内镜像地址
开源平台 链接
网易开源镜像★★★★ http://mirrors.163.com
清华大学★★★★★ https://mirrors.tuna.tsinghua.edu.cn/
中科大 http://mirrors.ustc.edu.cn/
东软信息学院 http://mirrors.neusoft.edu.cn/
linux官网镜像 https://mirrors.kernel.org/
阿里 http://mirrors.aliyun.com
搜狐 http://mirrors.sohu.com
浙大 http://mirrors.zju.edu.cn
华中科大 http://mirror.hust.edu.cn
兰州大学 http://mirror.lzu.edu.cn
重庆大学 http://mirrors.cqu.edu.cn
上海交大 http://ftp.sjtu.edu.cn
北京理工 http://mirror.bit.edu.cn/web/
南京大学 http://https://mirrors.nju.edu.cn
东北大学 http://mirror.neu.edu.cn
大连理工 http://mirror.dlut.edu.cn
郑州大学 http://mirrors.zzu.edu.cn
镜像加速器
# 1.执行以下命令,打开 /etc/docker/daemon.json 配置文件。
vim /etc/docker/daemon.json
# 2。 切换至编辑模式,添加以下内容,并保存
{
"registry-mirrors": [
"https://mirror.ccs.tencentyun.com",
"https://docker-0.unsee.tech",
"https://docker.m.daocloud.io"
]
}
# 3. 重启docker
sudo systemctl restart docker
# 4. 验证
docker info
基本操作
准备工作
下载安装docker
安装步骤:
# 安装依赖
yum install -y yum-utils device-mapper-persistent-data lvm2
# 添加软件源: 阿里云镜像源
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# 安装docker-ce
yum install -y docker-ce docker-ce-cli containerd.io
# 设置自启动
systemctl enable docker
注:上面的阿里云镜像源同样适用于opencloudOS系统
启动docker服务
# 启动docker服务
systemctl start docker
# 重启docker服务
systemctl restart docker
查看docker服务信息
# 查看docker版本
docker -v
# 查看docker服务详情信息
docker info
镜像加速器
国内阿里镜像加速器申请地址:https://cr.console.aliyun.com/cn-beijing/instances/mirrors
修改文件 /etc/docker/daemon.json
(如果不存在则需要创建创建,注意不要写入中文,要带 https://
),并重启服务。
# 创建目录
sudo mkdir -p /etc/docker
# 写入配置文件
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": [
"https://docker-0.unsee.tech",
"https://docker-cf.registry.cyou",
"https://docker.1panel.live"
]
}
EOF
# 重启docker服务
sudo systemctl daemon-reload && sudo systemctl restart docker
镜像 image
镜像相关的命令:
# 镜像仓库搜索镜像
docker search mysql
# 下载镜像
docker pull mysql:5.7
# 查看本地镜像
docker images
# 删除镜像
docker rmi image_id
# 使用tag命令为镜像添加标签
docker tag IMAGEID(镜像id) REPOSITORY:TAG(仓库:标签)
删除镜像是有条件限制的,如果该镜像创建的容器未被删除时,镜像是无法删除的,所以要删除一个镜像,必须先删除镜像所创建的容器。
容器 container
说下镜像和容器之间的关系,可以把docker 的镜像和容器比作程序中的类和对象。
docker run # 通过镜像创建并运行容器
docker start container_id # 启动现有容器
docker restart container_id # 重启现有容器
docker stop container_id # 停止容器
docker rm container_id # 删除容器
docker ps -a # 查看容器列表
docker update # 修改容器配置
创建并运行容器
docker run :创建一个新的容器
常用选项:
-d: 后台运行容器,并返回容器ID;
-p: 指定端口映射,格式为:主机(宿主)端口:容器端口
–name=”nginx-lb”: 为容器指定一个名称;
-i: 以交互模式运行容器,通常与 -t 同时使用;
-t: 为容器重新分配一个伪输入终端,通常与 -i 同时使用;
**-m :**设置容器使用内存最大值;
–net=”bridge”: 指定容器的网络连接类型,支持 bridge/host/none/container: 四种类型;
–volume , -v: 绑定一个卷
–link=[]: 添加链接到另一个容器(用来使容器互联);
–expose=[]: 开放一个端口或一组端口;
-e username=”ritchie”: 设置环境变量;
–env-file=[]: 从指定文件读入环境变量;
-h “mars”: 指定容器的hostname;
–dns 8.8.8.8: 指定容器使用的DNS服务器,默认和宿主一致;
例子:
# 示例一
docker run -d \
--name backend \
-p 30108:8080 \
--link redis:redis \
--link rabbit:rabbit \
--link mysql:mysql \
-v /root/yaml/backend/app:/app \
-v /data/sfs/amino-home:/amino-home
#示例二
docker run -d --name mysql-33061 -p 33061:3306 \
--network=mysql-net \
-v /var/data/mysql_1/data:/var/lib/mysql \
-v /var/data/mysql_1/my.cnf:/etc/my.cnf \
--restart=always -e MYSQL_ROOT_PASSWORD=root mysql:8.0.32
查看容器
# 查看正在运行的容器
docker ps
# 查看全部容器
docker ps -a
# 同 docker ps
docker container ls
# 查看某个容器的详情信息:
docker container inspect a969cf71a8a1
进入容器 exec
# 进入容器中:centos
docker exec -it container_id /bin/bash
# 进入容器中:alpine
docker exec -it container_id /bin/sh
设置容器自启动
# 在运行docker容器时可以加如下参数来保证每次docker服务重启后容器也自动重启:
docker run --restart=always
# 如果已经启动了则可以使用如下命令修改启动状态:
docker update --restart=always CONTAINER_ID
容器与宿主机复制数据 cp
docker cp 用于容器与宿主机之间进行数据拷贝:
# 将容器中的文件复制到宿主机中
docker cp 96f7f14e99ab:/www /tmp/
# 宿主机文件复制到容器中
docker cp onlyoffice.key 96f7f14e99ab:/app/
查看容器日志
# 查看实时日志
docker logs -f container
# 查看实时日志:只查看最后300行(效率高)
docker logs --tail=300 -f 4c6715dd9196
-f: 让 docker logs 像使用 tail -f 一样来输出容器内部的标准输出。
修改容器配置参数
两种方式修改容器的配置参数:
- 使用
docker container update
命令 - 修改配置文件
示例,比如 docker启动命令少了 --restart=always
参数,应该如何修改呢?
第一种:
docker container update --restart=always container_id
第二种:
首先停止容器,不然无法修改配置文件
配置文件路径为:/var/lib/docker/containers/container_id
,在该目录下找到一个文件 hostconfig.json
,找到该文件中关键字 RestartPolicy
修改前配置:”RestartPolicy”:{“Name”:”no”,”MaximumRetryCount”:0}
修改后配置:”RestartPolicy”:{“Name”:”always”,”MaximumRetryCount”:0}
最后启动容器。
commit
根据容器的更改创建新的镜像
docker commit -a "author" -m "message..." container_id
save / load
docker save 用于将一个或多个 image 镜像打包保存。
# 打包镜像
docker save -o [file_path/images.tar] image_name:tag1
docker save -o [file_path/images.tar] image_name:tag1 image_name2:tag2
# 加载镜像
docker load -i [file_path]
注:如果执行save 时不指定tag信息,那么load后的镜像是没有tag信息的。
export / import
docker export 用于将容器container进行打包。
docker run -i -t -d -p 5788:80 --restart=always \
-v /app/onlyoffice/DocumentServer/logs:/var/log/onlyoffice \
-v /app/onlyoffice/DocumentServer/data:/var/www/onlyoffice/Data onlyoffice/documentserver
docker save 和 docker export 的区别
- docker save 保存的是镜像,docker export 导出的是容器。
- docker load 用来加载镜像包,docker import 用来导入容器包,但二者都会恢复为镜像。
- docker load 不能为加载的镜像重命名,docker import 可以为镜像指定新名称。
查看元数据 inspect
docker inspect : 获取容器/镜像的元数据。
docker inspect 58f67442482e
命令汇总
Usage: docker [OPTIONS] COMMAND
Management Commands:
builder Manage builds
config Manage Docker configs
container Manage containers
context Manage contexts
image Manage images
network Manage networks
node Manage Swarm nodes
plugin Manage plugins
secret Manage Docker secrets
service Manage services
stack Manage Docker stacks
swarm Manage Swarm
system Manage Docker
trust Manage trust on Docker images
volume Manage volumes
Commands:
attach Attach local standard input,output,and error streams to a running container
build Build an image from a Dockerfile
commit Create a new image from a container's changes
cp Copy files/folders between a container and the local filesystem
create Create a new container
diff Inspect changes to files or directories on a container's filesystem
events Get real time events from the server
exec Run a command in a running container
export Export a container's filesystem as a tar archive
history Show the history of an image
images List images
import Import the contents from a tarball to create a filesystem image
info Display system-wide information
inspect Return low-level information on Docker objects
kill Kill one or more running containers
load Load an image from a tar archive or STDIN
login Log in to a Docker registry
logout Log out from a Docker registry
logs Fetch the logs of a container
pause Pause all processes within one or more containers
port List port mappings or a specific mapping for the container
ps List containers
pull Pull an image or a repository from a registry
push Push an image or a repository to a registry
rename Rename a container
restart Restart one or more containers
rm Remove one or more containers
rmi Remove one or more images
run Run a command in a new container
save Save one or more images to a tar archive (streamed to STDOUT by default)
search Search the Docker Hub for images
start Start one or more stopped containers
stats Display a live stream of container(s) resource usage statistics
stop Stop one or more running containers
tag Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE
top Display the running processes of a container
unpause Unpause all processes within one or more containers
update Update configuration of one or more containers
version Show the Docker version information
wait Block until one or more containers stop, then print their exit codes
Run 'docker COMMAND --help' for more information on a command.
网络
网络模式
Docker 容器的默认网络模式是 bridge
模式。当使用 docker run
启动容器时,若未指定网络参数,容器会自动连接到内置的 bridge
网络(名为 docker0
)。
在默认的 bridge
网络中:
- 容器间可以通过 IP 地址通信,但无法通过容器名称直接通信(需手动配置
--link
或使用自定义网络)。 - 容器与宿主机之间可以通信,容器通过
docker0
虚拟网桥连接到宿主机的网络。 - 容器可以访问外部网络(如互联网),通过宿主机的 NAT 规则实现。
管理网络
使用 docker network
命令管理网络
[root@erp-1 haya]# docker network --help
Usage: docker network COMMAND
Manage networks
Commands:
create # 创建一个网络
connect # 将容器连接到网络
disconnect # 断开容器与网络的连接
inspect # 查看网络详情信息
ls # 查看docker网络列表
prune # 删除所有未使用的网络
rm # 删除一个或多个网络
在使用 docker run
运行容器时通过 --net
参数来指定容器的网络配置,有4个可选值:
--net=bridge
这个是默认值,连接到默认的网桥。--net=host
告诉 Docker 不要将容器网络放到隔离的命名空间中,即不要容器化容器内的网络。此时容器使用本地主机的网络,它拥有完全的本地主机接口访问权限。容器进程可以跟主机其它 root 进程一样可以打开低范围的端口,可以访问本地网络服务比如 D-bus,还可以让容器做一些影响整个主机系统的事情,比如重启主机。因此使用这个选项的时候要非常小心。如果进一步的使用--privileged=true
,容器会被允许直接配置主机的网络堆栈。--net=container:NAME_or_ID
让 Docker 将新建容器的进程放到一个已存在容器的网络栈中,新容器进程有自己的文件系统、进程列表和资源限制,但会和已存在的容器共享 IP 地址和端口等网络资源,两者进程可以直接通过lo
环回接口通信。--net=none
让 Docker 将新容器放到隔离的网络栈中,但是不进行网络配置。之后,用户可以自己进行配置。
host 和 bridge 的区别
让容器使用host网络模式。这样做是确实可以避免端口映射的麻烦,也可利用host网络的高性能,因为host模式下容器直接使用宿主机的网络栈,没有NAT开销。
在Docker Compose 中,可以通过指定 network_mode: host 来让服务使用宿主机的网络。同时,需要注意,当使用host网络时,ports部分的端口映射可能不再需要,或者需要调整,因为容器会直接绑定到宿主机的端口上。
特性 | host 网络模式 |
自定义桥接网络 |
---|---|---|
网络隔离 | 无(共享宿主机网络) | 是(独立虚拟网络) |
容器名 DNS 解析 | 不支持 | 支持 |
通信方式 | 只能通过 localhost 或宿主机 IP |
直接通过容器名或 IP |
适用场景 | 高性能需求,避免 NAT 开销 | 多容器协作,需要隔离和 DNS 解析 |
DNS 解析
docker 默认的bridge 网络和自定义的bridge 有什么区别?
- 默认
bridge
网络:
容器之间只能通过 IP 地址 通信。若要通过容器名称访问,必须使用--link
参数,且仅支持单向通信。 - 自定义bridge网络:
容器加入同一自定义网络后,可通过 容器名称 或 自定义别名 直接通信,无需手动配置。
验证 DNS 解析
在自定义桥接网络中,可以在容器内测试 DNS 解析:
# 进入容器 A 的 shell
docker exec -it containerA sh
# 测试解析 containerB 的 IP
nslookup containerB
最佳实践
# 查看docker网络列表
docker network ls
# 创建自定义网络: bridge 类型
docker network create custom-net
# 启动容器并加入自定义网络
docker run -d --name container-1 --network custom-net nginx
# 将运行中的容器连接到新网络
docker network connect custom-net container-2
# 断开容器与某个网络的连接
docker network disconnect custom-net container-2
# 查看哪些容器在指定网络中
docker network inspect study_default
注意
- 端口映射:在
bridge
模式下,需通过-p
参数暴露端口到宿主机。 - DNS 解析:仅自定义网络支持通过容器名称自动解析 IP。
- 网络隔离:不同网络中的容器默认无法通信(需显式连接)
数据卷
使用 docker volume
命令管理数据卷
[root@erp-1 haya]# docker volume --help
Usage: docker volume COMMAND
Manage volumes
Commands:
create # 创建一个数据卷
inspect # 查看docker数据卷的详情信息
ls # 查看docker数据卷列表
prune # 删除所有未使用的数据卷
rm # 删除一个或多个数据卷
运行容器时,可通过 -v
选项指定数据卷
语法
docker run -v /var/log/jeomo:/var/log/jeomo
示例:
docker run -d -v /var/log/jeomo:/var/log/jeomo -p 9797:9797 --name jeomo jeomo
Dockerfile
Dockerfile提供了从无到有的构建自定义镜像的能力,它包含安装运行所需的环境、程序代码等。这个创建过程就是使用 dockerfile 来完成的。
示例1:
FROM openjdk:11
MAINTAINER Jackpot
ENV SPRING_OUTPUT_ANSI_ENABLED=ALWAYS \
JAVA_OPTS="-Xms1024m -Xmx1024m -XX:PermSize=256m -XX:MaxPermSize=512m -XX:+UseG1GC" \
PORT=8501 \
PROFILES="default"
ADD /target/*.jar /bookstore-warehouse.jar
ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -jar /bookstore-warehouse.jar --spring.profiles.active=$PROFILES"]
EXPOSE $PORT
构建java应用
FROM openjdk:11
ADD build/libs/gbc-war-*.war app.war
ADD docker/application.yml application.yml
ADD docker/log4j2.xml /app/log4j2-default.xml
ENTRYPOINT ["java","-jar","app.war"]
构建前端应用
FROM 10.2.24.210:18081/library/nginx:v1.0.0
COPY dist/ /usr/share/nginx/html/
CMD ["nginx", "-g", "daemon off;"]
示例:基于已有镜像安装ffmpeg
FROM libreoffice:latest
MAINTAINER WangGuodong
ADD ffmpeg-6.1.1 /opt/ffmpeg-6.1.1
ADD yasm-1.3.0 /opt/yasm-1.3.0
RUN yum install -y gcc automake autoconf libtool make
RUN cd /opt/yasm-1.3.0 && ./configure && make && make install
RUN cd /opt/ffmpeg-6.1.1 && ./configure --prefix=/usr/local/ffmpeg && make && make install
ENV PATH=$PATH:/usr/local/ffmpeg/bin
指令详解
COPY
复制指令,从上下文目录中复制文件或者目录到容器里指定路径。
# 语法
COPY [--chown=<user>:<group>] <源路径1>... <目标路径>
# 示例
COPY dist/ /usr/share/nginx/html/
注:
- 源文件或者源目录,这里可以是通配符表达式,其通配符规则要满足 Go 的 filepath.Match 规则。
- 目标路径为容器内的指定路径,该路径不用事先建好,路径不存在的话,会自动创建。
ADD
ADD 指令和 COPY 的使用格类似(同样需求下,官方推荐使用 COPY)。功能也类似,不同之处如下:
- ADD 的优点:在执行 <源文件> 为 tar 压缩文件的话,压缩格式为 gzip, bzip2 以及 xz 的情况下,会自动复制并解压到 <目标路径>。
- ADD 的缺点:在不解压的前提下,无法复制 tar 压缩文件。会令镜像构建缓存失效,从而可能会令镜像构建变得比较缓慢。具体是否使用,可以根据是否需要自动解压来决定。
RUN
构建镜像时运行的指令
示例:
FROM openjdk:11
COPY . /usr/src/myapp
WORKDIR /usr/src/myapp
RUN javac Main.java
CMD ["java", "Main"]
CMD
类似于 RUN 指令,用于运行程序,但二者运行的时间点不同:
- RUN 是在 docker build 时运行
- CMD 在docker run 时运行
#语法
CMD <shell 命令>
CMD ["<可执行文件或命令>","<param1>","<param2>",...]
CMD ["<param1>","<param2>",...] # 该写法是为 ENTRYPOINT 指令指定的程序提供默认参数
#示例
注:
- 推荐使用第二种格式,执行过程比较明确。第一种格式实际上在运行的过程中也会自动转换成第二种格式运行,并且默认可执行文件是 sh。
- 如果 Dockerfile 中如果存在多个 CMD 指令,仅最后一个生效。
ENTRYPOINT
类似于 CMD 指令,但其不会被 docker run 的命令行参数指定的指令所覆盖,而且这些命令行参数会被当作参数送给 ENTRYPOINT 指令指定的程序。但是, 如果运行 docker run 时使用了 –entrypoint 选项,将覆盖 ENTRYPOINT 指令指定的程序。
在执行 docker run 的时候可以指定 ENTRYPOINT 运行所需的参数。可以搭配 CMD 命令使用:一般是变参才会使用 CMD ,这里的 CMD 等于是在给 ENTRYPOINT 传参,以下示例会提到。
注:如果 Dockerfile 中如果存在多个 ENTRYPOINT 指令,仅最后一个生效。
#语法
ENTRYPOINT ["<executeable>","<param1>","<param2>",...]
#示例
FROM nginx
ENTRYPOINT ["nginx", "-c"] # 定参
CMD ["/etc/nginx/nginx.conf"] # 变参
第一种:不传参运行
docker run nginx:test
#容器内会默认运行以下命令启动主进程
nginx -c /etc/nginx/nginx.conf
第二种:传参运行
docker run nginx:test -c /etc/nginx/new.conf
#容器内会运行以下命令启动主进程
nginx -c /etc/nginx/new.conf
ENV
设置环境变量,定义了环境变量,那么在后续的指令中,就可以使用这个环境变量。
# 语法
ENV <key> <value>
ENV <key1>=<value1> <key2>=<value2>...
#示例
ENV NODE_VERSION 7.2.0
RUN curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc"
ARG
构建参数,与 ENV 作用一致。不过作用域不一样。ARG 设置的环境变量仅对 Dockerfile 内有效,也就是说只有 docker build 的过程中有效,构建好的镜像内不存在此环境变量。
构建命令 docker build 中可以用 –build-arg <参数名>=<值> 来覆盖。
#语法
ARG <参数名>[=<默认值>]
VOLUME
定义匿名数据卷。在启动容器时忘记挂载数据卷,会自动挂载到匿名卷。
作用:
- 避免重要的数据,因容器重启而丢失,这是非常致命的。
- 避免容器不断变大。
#语法
VOLUME ["<路径1>", "<路径2>"...]
VOLUME <路径>
EXPOSE
仅仅只是声明端口。
作用:
- 帮助镜像使用者理解这个镜像服务的守护端口,以方便配置映射。
- 在运行时使用随机端口映射时,也就是 docker run -P 时,会自动随机映射 EXPOSE 的端口。
格式:
EXPOSE <端口1> [<端口2>...]
WORKDIR
指定工作目录。用 WORKDIR 指定的工作目录,会在构建镜像的每一层中都存在。以后各层的当前目录就被改为指定的目录,如该目录不存在,WORKDIR 会帮你建立目录。
docker build 构建镜像过程中的,每一个 RUN 命令都是新建的一层。只有通过 WORKDIR 创建的目录才会一直存在。
#语法
WORKDIR <工作目录路径>
USER
用于指定执行后续命令的用户和用户组(用户和用户组必须提前已经存在)。
#语法
USER <用户名>[:<用户组>]
LABEL
LABEL 指令用来给镜像添加一些元数据(metadata),以键值对的形式,语法格式如下:
#语法
LABEL <key>=<value> <key>=<value> <key>=<value> ...
# 示例
LABEL org.opencontainers.image.authors="Jackpot"
指令 | 说明 |
---|---|
FROM | 构建镜像基于哪个镜像 |
MAINTAINER | 镜像维护者(姓名或邮箱) |
RUN | 构建镜像时运行的指令 |
CMD | 运行容器时运行的指令 |
ENTRYPOINT | 运行容器时执行的shell命令 |
COPY | 拷贝文件或目录到容器中,跟ADD类似,但不具备自动下载或解压的功能 |
ADD | 拷贝文件或目录到容器中,如果是URL或压缩包便会自动下载或自动解压 |
ENV | 设置容器环境变量 |
ARG | 构建时指定的一些参数 |
WORKDIR | 设置工作目录,就是切换目录 |
USER | 为执行后续命令指定运行用户 |
VOLUME | 指定容器挂载点到宿主机自动生成的目录或其他容器 |
EXPOSE | 声明容器的服务端口(仅仅是声明) |
构建镜像
使用 docker build
命令构建镜像。
# 查看帮助
docker build --help
#
docker build .
docker build -f ./Dockerfile
# 构建时指定镜像名称:tag
docker build -t oracle-jdk:v17 .
最佳实践
选择一个稳定的、体积较小的基础镜像是非常有必要的。
为什么选择 Debian Slim?
- 适合容器化:体积小、启动快,符合容器“单一进程”的最佳实践。
- 兼容性无忧:基于
glibc
,可直接运行 Java、.NET Core 等依赖标准库的应用。 - 安全更新及时:Debian 提供长期安全维护(LTS),适合企业级应用。
Debian Slim与常规 Debian 镜像的区别
对比项 | Debian 标准镜像 (debian:stable ) |
Debian Slim (debian:stable-slim ) |
---|---|---|
体积 | ~120MB | ~50MB |
预装软件 | 包含 man 文档、apt 工具链等 |
仅基础工具(如 libc6 、tar 、gzip ) |
适用场景 | 需要完整系统功能的场景 | 容器化环境(追求极简和高效) |
在 Dockerfile 中使用 Debian stable:
# 使用稳定的 Debian 作为基础镜像, 此外还有更轻量级的选择 debian:stable-slim
FROM debian:stable
# 设置中国时区
ENV TZ=Asia/Shanghai
RUN apt update && apt install -y --no-install-recommends tzdata \
&& ln -sf /usr/share/zoneinfo/${TZ} /etc/localtime \
&& echo ${TZ} > /etc/timezone
ENV JAVA_VERSION="jdk-21.0.6" # 注意这个名称是tar包解压后的名称
ENV JAVA_HOME="/opt/${JAVA_VERSION}"
ENV PATH="${PATH}:${JAVA_HOME}/bin"
ADD jdk-21.0.6.tar.gz /opt/
注:以上脚本亲测可用。其中debian:stable 层约120M,tzdata 时区数据包约20M,解压后的jdk21约350M,最后构建出的镜像约490M。
# 使用命令构建镜像
docker build -t debian-stable-jkd:v21 .
docker-compose
Docker Compose 是 Docker 官方的开源项目,负责在单机上实现对多个 Docker容器的快速编排。Compose 工具使用 YML文件来配置应用程序的服务,然后使用一个命令就可以从配置中创建并启动所有服务。
使用步骤
使用 Compose 基本上需要三步:
使用
Dockerfile
文件定义应用程序的环境,以便可以在任何地方复制它。在
docker-compose.yml
文件中定义构成应用程序的服务,以便它们可以在隔离环境中一起运行。运行
docker compose up
命令启动并运行您的整个应用程序。
下面是一个示例:
客户端通过网络访问前端服务的443安全认证端口,前端服务访问另一个后端服务。
(External user) --> 443 [frontend network]
|
+--------------------+
| frontend service |...ro...<HTTP configuration>
| "webapp" |...ro...<server certificate> #secured
+--------------------+
|
[backend network]
|
+--------------------+
| backend service | r+w ___________________
| "database" |=======( persistent volume )
+--------------------+ \_________________/
示例应用程序由以下部分组成:
- 2 个服务,由 Docker 镜像支持:webapp 和数据库
- 1 个秘密(HTTPS 证书),注入到前端
- 1 配置,注入到前端
- 1 个持久卷,附加到后端
- 2个网络
compose.yaml
services:
frontend:
image: awesome/webapp
ports:
- "443:8043"
networks:
- front-tier
- back-tier
configs:
- httpd-config
secrets:
- server-certificate
backend:
image: awesome/database
volumes:
- db-data:/etc/data
networks:
- back-tier
volumes:
db-data:
driver: flocker
driver_opts:
size: "10GiB"
configs:
httpd-config:
external: true
secrets:
server-certificate:
external: true
networks:
# The presence of these objects is sufficient to define them
front-tier: {}
back-tier: {}
compose file
Compose 文件是一个 YAML 文件,用于定义服务(必需)、网络、卷、配置和安全证书。 Compose 文件的默认路径是工作目录中的 compose.yaml 或 compose.yml。 Compose 实现还应该支持 docker-compose.yaml 和 docker-compose.yml 以实现向后兼容性。
可以将多个 Compose 文件组合在一起来定义应用程序模型。
注:Compose 文件中定义版本(已弃用)
services
image
image 指定启动容器的镜像。
ports
公开容器端口
ports:
- "3000"
- "3000-3005"
- "8000:8000"
- "9090-9091:8080-8081"
- "49100:22"
- "8000-9000:80"
- "127.0.0.1:8001:8001"
- "127.0.0.1:5000-5010:5000-5010"
- "6060:6060/udp"
networks
networks 定义服务容器所连接的网络,引用顶级网络配置下的条目。
services:
some-service:
networks:
- some-network
- other-network
networks: # 网络
some-network: # 网络名称
driver: bridge
other-network:
network_mode
network_mode 设置服务容器网络模式。 可用值是特定于平台的,但 Compose 规范定义了特定的值,如果支持,必须按照描述的方式实现这些值:
none
禁用所有容器网络host
赋予容器对主机网络接口的原始访问权限service:{name}
只允许容器访问指定的服务
links
web:
links:
- db
- db:database
- redis
restart
- no:是默认的重启策略,在任何情况下都不会重启容器。
- always:容器总是重新启动。
- on-failure:在容器非正常退出时(退出状态非0),才会重启容器。
- unless-stopped:在容器退出时总是重启容器,但是不考虑在Docker守护进程启动时就已经停止了的容器
restart: "no"
restart: always
restart: on-failure
restart: unless-stopped
depend_on
depends_on 表示服务之间的启动和关闭依赖关系。它有两种语法:短语法和长语法。
短语法:
services:
web:
build: .
depends_on:
- db
- redis
redis:
image: redis
db:
image: postgres
Compose 实现必须按依赖顺序创建服务。 在下面的示例中,db 和 redis 在 web 之前创建。
Compose 实现必须按依赖顺序删除服务。 在以下示例中,web 在 db 和 redis 之前被删除。
长语法:
services:
web:
build: .
depends_on:
db:
condition: service_healthy
restart: true
redis:
condition: service_started
redis:
image: redis
db:
image: postgres
注意:
depends_on
无法跨 Compose 文件控制启动顺序。需手动确保依赖服务先启动。也就是说depends_on 依赖的服务,必须在本compose文件中声明,否则就不合法。
configs
configs
用于指定服务的配置项,它有两种语法:短语法和长语法,可以单独使用其中一种,也可以混合使用。
短语法:
services:
redis:
image: redis:latest
configs:
- my_config
- my_other_config
configs:
my_config:
file: ./my_config.txt
my_other_config:
external: true
长语法:
services:
redis:
image: redis:latest
configs:
- source: my_config
target: /redis_config
uid: "103"
gid: "103"
mode: 0440
configs:
my_config:
external: true
my_other_config:
external: true
volumes
将主机的数据卷或着文件挂载到容器里。格式:HOST_PATH:CONTAINER_PATH
volumes:
- "/localhost/postgres.sock:/var/run/postgres/postgres.sock"
- "/localhost/data:/var/lib/postgresql/data"
environment
添加环境变量。您可以使用数组或字典、任何布尔值,布尔值需要用引号引起来,以确保 YML 解析器不会将其转换为 True 或 False。
Map 语法:
environment:
RACK_ENV: development
SHOW: "true"
数组 语法:
environment:
- RACK_ENV=development
- SHOW="true"
env_file
从文件添加环境变量。可以是单个值或列表的多个值。
env_file: ./a.env
或
env_file:
- ./a.env
- ./b.env
配置文件格式:
# Set Rails/Rack environment
RACK_ENV=development
VAR="quoted"
expose
暴露端口,但不映射到宿主机,只被连接的服务访问。
仅可以指定内部端口为参数:
expose:
- "3000"
- "8000"
extends
extends:
file: common.yml
service: webapp
container_name
container_name 是一个字符串,用于指定自定义容器名称,而不是生成的默认名称。
container_name: my-web-container
command
命令
command 用于覆盖容器镜像声明的默认命令(即通过 Dockerfile 的 CMD)。
command: bundle exec thin -p 3000
该值也可以是一个列表,其方式类似于 Dockerfile:
command: [ "bundle", "exec", "thin", "-p", "3000" ]
如果值为null
,则必须使用图像中的默认命令。
如果值为 []
(空列表)或 ''
(空字符串),则必须忽略图像声明的默认命令,即重写为空。
sysctls
设置容器中的内核参数,可以使用数组或字典格式。
sysctls:
net.core.somaxconn: 1024
net.ipv4.tcp_syncookies: 0
sysctls:
- net.core.somaxconn=1024
- net.ipv4.tcp_syncookies=0
blkio_config
blkio_config 定义了一组配置选项来设置此服务的块 IO 限制。
services:
foo:
image: busybox
blkio_config:
weight: 300
weight_device:
- path: /dev/sda
weight: 400
device_read_bps:
- path: /dev/sdb
rate: '12mb'
device_read_iops:
- path: /dev/sdb
rate: 120
device_write_bps:
- path: /dev/sdb
rate: '1024k'
device_write_iops:
- path: /dev/sdb
rate: 30
weight 权重 :
修改分配给该服务的带宽相对于其他服务的比例。 采用 10 到 1000 之间的整数值,默认值为 500。
权重设备 weight_device:
按设备微调带宽分配。 列表中的每一项都必须有两个键:
路径:定义受影响设备的符号路径。
权重:10 到 1000 之间的整数值。
device_read_bps, device_write_bps
为给定设备上的读/写操作设置每秒字节数限制。 列表中的每个项目必须有两个键:
路径:定义受影响设备的符号路径。
rate:作为表示字节数的整数值或作为表示字节值的字符串。
device_read_iops, device_write_iops
为给定设备上的读/写操作设置每秒操作数限制。 列表中的每个项目必须有两个键:
路径:定义受影响设备的符号路径。
速率:表示每秒允许的操作数的整数值。
cpu_count
定义了服务容器可用的 CPU 数量。
更多限制参数请查看官方文档。
dns
自定义 DNS 服务器,可以是单个值或列表的多个值。
dns: 8.8.8.8
#
dns:
- 223.5.5.5
- 114.114.114.114
dns_search
自定义 DNS 搜索域。可以是单个值或列表。
dns_search: example.com
#
dns_search:
- dc1.example.com
- dc2.example.com
configs
networks
networks:
cus-bridge-net:
external: true
如果在docker-compose
文件中设置external
为true
,那么使用docker-compose up -d
来启动服务时,首先docker
引擎会查找external
声明的网络,找到后进行连接。否则会提示错误
当其值为false
时,会自动创建一个testProject_bennet
的网络,如果没有networks
字段时,会创建一个testProject_default
的网络。
volumes
secrets
存储敏感数据,例如密码:
services:
mysql:
image: mysql
environment:
MYSQL_ROOT_PASSWORD_FILE: /run/secrets/my_secret
secrets:
- my_secret
secrets:
my_secret:
file: ./my_secret.txt
profiles
示例:
services:
foo:
image: foo
bar:
image: bar
profiles:
- test
baz:
image: baz
depends_on:
- bar
profiles:
- test
zot:
image: zot
depends_on:
- bar
profiles:
- debug
说明:
- 在未启用配置文件的情况下,解析的组合应用程序模型仅包含 foo 服务。
- 如果启用配置文件test,则模型包含由测试配置文件启用的服务 bar 和 baz 以及始终启用的服务 foo。
- 如果启用配置文件debug,模型包含 foo 和 zot 服务,但不包含 bar 和 baz,因此模型对于 zot 的 depends_on 约束是无效的。
- 如果配置文件debug和test启用,模型包含所有服务:foo、bar、baz 和 zot。
构建
1.在项目目录下创建一个 docker-compose.yml
文件
services: # 服务列表
node: # 服务名称:node
build: . # Dockerfile 的目录,用于构建镜像
container_name: node-server-1 # 容器名称
ports: # 暴露的端口
- "3000:3000"
restart: always # 自动重启
environment: # 设置环境变量
- NODE_ENV=production
command: npm run start # 覆盖容器启动后默认执行的命令
2.构建镜像
docker-compose build
3.运行容器
docker-compose up -d
重新构建
# 删除上次构建的容器
docker-compose down
# 重新构建镜像 --force-rm 删除构建过程中的临时容器。
docker-compose build --force-rm
安装
Linux 上我们可以从 Github 上下载它的二进制包来使用,最新发行的版本地址:https://github.com/docker/compose/releases。
运行以下命令以下载 Docker Compose 的当前稳定版本:
$ sudo curl -L "https://github.com/docker/compose/releases/download/v2.17.3/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
要安装其他版本的 Compose,请替换 v2.17.3。如果网速太慢,也可以将二进制包下载好上传到服务器指定位置。
将可执行权限应用于二进制文件:
chmod +x /usr/local/bin/docker-compose
创建软链:
ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose
测试是否安装成功:
docker-compose version
cker-compose version 2.17.3, build 4667896b
kompose
kompose 是K8s官方推荐的 Docker Compose 到 Kubernetes 的转换工具。具体操作请看这里。
多机部署
前面的docker compose 用于在单个机器上部署多个容器服务,当我们需要在多个物理机上部署容器服务时,应该怎么做呢
Docker Swarm
Docker 官方提供了Swarm 来管理多机环境下的集群部署,但因为Kubernates 在这方面做得更加出色,而且市场占有率更高,本文就不花额外的时间来研究和学习Docker Swarm了。
Kubernates
Kubernates,简称K8s。
K3s
高级进阶
容器单一进程
在 Docker 容器中,建议只运行一个前台进程。这是 Docker 官方和容器化最佳实践的核心原则之一。以下是详细解释和建议:
为什么建议只运行一个前台进程?
原因 | 说明 |
---|---|
单一职责 | 每个容器应专注于一个任务(如运行一个应用、一个服务),符合微服务设计理念。 |
生命周期管理 | Docker 通过监控容器内的前台进程(PID 1)管理容器生命周期。多个前台进程会导致信号(如 SIGTERM )无法正确传递。 |
日志隔离 | 多个进程的日志会混合在容器的标准输出(stdout/stderr )中,难以追踪问题。 |
资源控制 | 单个进程更易通过 --memory 、--cpus 等参数限制资源使用。 |
扩展性 | 横向扩展时,可以独立扩展每个服务(每个容器对应一个服务)。 |
特别注意:在一个docker容器中,至少存在一个前台进程,如果不存在前台进程,则容器停止。
始终优先遵循 “一个容器,一个进程” 原则,仅在绝对必要时运行多个进程。
升级容器权限
--privileged
是 Docker 中的一个参数,用于在启动容器时赋予容器几乎与宿主机相同的权限。具体来说,使用 --privileged
参数后,容器内的进程可以访问宿主机的所有设备,并且可以执行一些通常需要高级权限的操作,例如加载内核模块、挂载文件系统等。
默认情况下,Docker 会限制容器的权限,禁用一些潜在危险的内核功能,以增强安全性。然而,--privileged
参数会解除这些限制,使容器能够执行更多操作,甚至可以在容器内运行 Docker 本身。总结来说,--privileged
参数赋予容器更高的权限,允许它执行更多操作,但同时也增加了安全风险。
下面的例子就用到了:
docker run -d \
--name mysql8 \
-p 3306:3306 \
--privileged \
--restart=always \
-v E:/var/mysql8/conf/my.cnf:/etc/mysql/my.cnf \
-v E:/var/mysql8/logs:/logs \
-v E:/var/mysql8/data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=123 \
mysql:8.4
私有仓库
有时候使用 Docker Hub 这样的公共仓库可能不方便,用户可以创建一个私有仓库供自己使用。
Docker Registry
安装运行 docker-registry
docker run -d \
-p 5000:5000 \
-v /opt/data/registry:/var/lib/registry \
registry
这将使用官方的 registry
镜像来启动私有仓库。默认情况下,仓库会被创建在容器的 /var/lib/registry
目录下。你可以通过 -v
参数来将镜像文件存放在本地的指定路径。例如下面的例子将上传的镜像放到本地的 /opt/data/registry
目录。
创建好私有仓库之后,就可以使用 docker tag
来标记一个镜像,然后推送它到仓库。例如私有仓库地址为 127.0.0.1:5000
。
使用 docker tag
将 ubuntu:latest
这个镜像标记为 127.0.0.1:5000/ubuntu:latest
。
$ docker tag ubuntu:latest 127.0.0.1:5000/ubuntu:latest
$ docker image ls
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
ubuntu latest ba5877dc9bec 6 weeks ago 192.7 MB
127.0.0.1:5000/ubuntu:latest latest ba5877dc9bec 6 weeks ago 192.7 MB
使用 docker push
上传标记的镜像。
$ docker push 127.0.0.1:5000/ubuntu:latest
用 curl
查看仓库中的镜像:
$ curl 127.0.0.1:5000/v2/_catalog
{"repositories":["ubuntu"]}
Nexus 3
使用 Docker 官方的 Registry 创建的仓库面临一些维护问题。比如某些镜像删除以后空间默认是不会回收的,需要一些命令去回收空间然后重启 Registry。在企业中把内部的一些工具包放入 Nexus
中是比较常见的做法,最新版本 Nexus3.x
全面支持 Docker 的私有镜像。所以使用 Nexus3.x
一个软件来管理 Docker
, Maven
, Yum
, PyPI
等是一个明智的选择。
$ docker run -d --name nexus3 --restart=always \
-p 8081:8081 \
--mount src=nexus-data,target=/nexus-data \
sonatype/nexus3
镜像分层
Docker 支持通过扩展现有镜像,创建新的镜像。实际上,Docker Hub 中几乎所有镜像都是通过在 base 镜像中安装和配置需要的软件构建出来的。

从上图可以看到,新镜像是从 base 镜像一层一层叠加生成的。每安装一个软件,就在现有镜像的基础上增加一层。
镜像分层的原因
镜像分层最大的一个好处就是共享资源。
比如说有多个镜像都从相同的 base 镜像构建而来,那么 Docker Host 只需在磁盘上保存一份 base 镜像;同时内存中也只需加载一份 base 镜像,就可以为所有容器服务了。而且镜像的每一层都可以被共享。
如果多个容器共享一份基础镜像,当某个容器修改了基础镜像的内容,比如 /etc 下的文件,这时其他容器的 /etc 是不会被修改的,修改只会被限制在单个容器内。这就是容器 Copy-on-Write 特性、
可写的容器层
当容器启动时,一个新的可写层被加载到镜像的顶部。这一层通常被称作“容器层”,“容器层”之下的都叫“镜像层”。

所有对容器的改动 - 无论添加、删除、还是修改文件都只会发生在容器层中。只有容器层是可写的,容器层下面的所有镜像层都是只读的。
镜像层数量可能会很多,所有镜像层会联合在一起组成一个统一的文件系统。如果不同层中有一个相同路径的文件,比如 /a,上层的 /a 会覆盖下层的 /a,也就是说用户只能访问到上层中的文件 /a。在容器层中,用户看到的是一个叠加之后的文件系统。
文件操作说明
文件操作 | 说明 |
---|---|
添加文件 | 在容器中创建文件时,新文件被添加到容器层中。 |
读取文件 | 在容器中读取某个文件时,Docker 会从上往下依次在各镜像层中查找此文件。一旦找到,立即将其复制到容器层,然后打开并读入内存。 |
修改文件 | 在容器中修改已存在的文件时,Docker 会从上往下依次在各镜像层中查找此文件。一旦找到,立即将其复制到容器层,然后修改之。 |
删除文件 | 在容器中删除文件时,Docker 也是从上往下依次在镜像层中查找此文件。找到后,会在容器层中记录下此删除操作。(只是记录删除操作) |
只有当需要修改时才复制一份数据,这种特性被称作 Copy-on-Write。可见,容器层保存的是镜像变化的部分,不会对镜像本身进行任何修改。
这样就解释了我们前面提出的问题:容器层记录对镜像的修改,所有镜像层都是只读的,不会被容器修改,所以镜像可以被多个容器共享。
操作系统
Docker启动的容器默认使用Docker镜像中指定的Linux发行版。Docker镜像是由Dockerfile构建而来的,其中指定了基础镜像(base image),该基础镜像中包含了操作系统和所需的软件包。
如果Dockerfile中未指定基础镜像,Docker会默认使用 Debian 作为操作系统。如果需要使用其他的Linux发行版,可以在Dockerfile中指定相应的基础镜像,例如Ubuntu、CentOS等。
root@a4c11063189e:/# cat /etc/os-release
PRETTY_NAME="Debian GNU/Linux 11 (bullseye)"
NAME="Debian GNU/Linux"
VERSION_ID="11"
注意,使用 CentOS直接作为业务应用容器的基础镜像是非常不建议的,因为这样做出来的镜像,不仅镜像的体积比较大,而且CentOS安装了很多业务应用程序用不到的包,可能会有更多的漏洞和风险。
对于基础镜像的选择,比较常用的有Alpine、Debian、Busybox 等。每种基础镜像的包管理方式可能有所差异,比如Alpine的包管理工具是 APK,对于没有接触过Alpine系统的读者会有所陌生,但是Alpine是目前最流行的基础镜像之一,因为Alpine不仅体积小、使用简单,同时也包含排查相关问题的基本工具。
配置文件
/etc/docker/daemon.json
是 Docker 守护进程的配置文件,用于配置 Docker 引擎的行为和选项。在该文件中,你可以指定各种配置参数,以影响 Docker 守护进程的运行方式。
下面是一些常见的配置选项及其用途:
log-driver
:指定 Docker 容器日志的驱动程序,用于将容器的日志输出路由到指定的日志驱动程序,如 json-file、syslog、journald 等。log-opts
:用于指定日志驱动程序的配置选项,例如日志的最大大小、最大文件数等。storage-driver
:指定 Docker 存储驱动程序,用于管理镜像和容器的存储。常见的存储驱动程序包括 overlay2、aufs、btrfs 等。insecure-registries
:用于配置 Docker 守护进程信任的不安全的 Docker 镜像仓库地址。默认情况下,Docker 只信任使用 TLS(Transport Layer Security)加密的镜像仓库。使用此选项可以指定不使用 TLS 加密的镜像仓库地址。registry-mirrors
:指定 Docker 镜像仓库的镜像地址,以加速镜像的拉取和推送操作。可以配置多个镜像地址,Docker 将尝试从镜像地址中选择最快的镜像进行操作。default-ulimits
:指定容器的默认资源限制。可以设置容器可以使用的 CPU、内存等资源的限制。dns
:指定容器的 DNS 服务器。可以配置一个或多个 DNS 服务器地址。exec-opts
:用于指定在容器内执行命令时的选项,如设置超时时间、环境变量等。
以上只是一些示例配置选项,实际可以在 daemon.json
文件中配置的选项更多。配置文件的具体语法和选项取决于 Docker 的版本和你的特定需求。
在修改 daemon.json
文件后,你需要重新加载或重启 Docker 守护进程以使更改生效。请注意,修改 Docker 的配置可能会对系统和容器的行为产生重大影响,因此在修改配置之前请确保了解各个选项的含义和影响,并谨慎操作。
示例:
vi /etc/docker/daemon.json
{ "insecure-registries":["registry:5000"] }
# 重新加载
systemctl daemon-reload
systemctl enable docker && systemctl restart docker
容器运行时
Containerd 是一个强调简单性、健壮性和可移植性的行业标准容器运行时。2019年2月28日,containerd正式成为云原生计算基金会(CNCF)的毕业项目,继Kubernetes、Prometheus、Envoy、CoreDNS之后。
Docker和Containerd是两个与容器相关的开源项目,它们在容器生态系统中扮演不同的角色。
Docker是一个流行的容器化平台,提供了创建、部署和管理容器化应用程序的工具和功能。它包括了三个主要组件:
Docker引擎(Docker Engine):Docker引擎是Docker的核心组件,负责构建和运行容器。它使用容器化技术,如Linux容器(LXC)和操作系统级虚拟化(如cgroups和命名空间),来隔离应用程序和依赖项,并提供一个一致的运行环境。
Docker映像(Docker Images):Docker映像是应用程序和其所有依赖项的打包格式。通过使用Docker映像,可以轻松地创建和共享容器化应用程序。映像可以基于Dockerfile定义,其中包含了构建映像所需的指令和配置。
Docker仓库(Docker Hub):Docker仓库是一个集中存储和共享Docker映像的地方。Docker Hub是Docker官方的公共仓库,用户可以从中下载和分享Docker映像。此外,用户还可以搭建私有的Docker仓库来存储和管理自己的映像。
Containerd是一个独立的容器运行时,它专注于容器的生命周期管理。Containerd提供了一组API和工具,用于控制容器的创建、运行和销毁。它被设计为一个高度可扩展的系统,并支持多种容器运行时(包括Docker引擎)的后端。实际上,Docker引擎的容器运行时组件内部使用了Containerd来管理容器的生命周期。
总结一下:
- Docker是一个完整的容器化平台,包括Docker引擎、Docker映像和Docker仓库,用于构建、运行和分享容器化应用程序。
- Containerd是一个独立的容器运行时,专注于容器的生命周期管理,被多个容器平台和工具用作底层的容器运行时。Docker引擎的容器运行时(Container Runtime)组件内部使用了Containerd。
部署实战
部署Java后端
需要:编译后的jar包,配置文件、openjdk:11镜像、Redis、mysql
目录结构:
./
├── app
│ ├── application-test.yml
│ ├── inz.jar
└── start.sh
startup.sh:
docker stop edu-backend
docker rm edu-backend
docker run -d \
--name edu-backend \
-p 8071:8080 \
--link redis:redis \
-v /root/education/study/backend/app:/app \
openjdk:11 sh -c ' cd /app && java -Xmx2G -Xms1G -Xmn1024M -XX:MaxDirectMemorySize=1256m -jar /app/inz.jar --spring.profiles.active=test'
docker-compose.yml
services:
mall4cloud-leaf:
image: debian-stable-jdk:v21
container_name: mall4cloud-leaf
restart: always
ports:
- "9100:9100"
command: sh -c "cd /app && java -Xms256m -Xmx512m -DNACOS_HOST=mall4cloud-nacos -DMYSQL_HOST=mysql8 -DMYSQL_PASSWORD=123 -Dserver.port=9100 -Dspring.profiles.active=dev -Dfile.encoding=utf-8 -jar /app/mall4cloud-leaf.jar"
volumes:
- E:/mall4cloud_package/mall4cloud-leaf:/app
networks:
- custom-bridge-net
mall4cloud-auth:
image: debian-stable-jdk:v21
container_name: mall4cloud-auth
restart: always
ports:
- "9101:9101"
command: sh -c "cd /app && java -Xms256m -Xmx512m -DNACOS_HOST=mall4cloud-nacos -DMYSQL_HOST=mysql8 -DMYSQL_PASSWORD=123 -Dserver.port=9101 -Dspring.profiles.active=dev -Dfile.encoding=utf-8 -jar /app/mall4cloud-auth.jar"
volumes:
- E:/mall4cloud_package/mall4cloud-auth:/app
networks:
- custom-bridge-net
networks:
custom-bridge-net:
external: true
部署前端
需要:编译后的dist静态文件包、应用配置文件、Nginx、Nginx配置文件
目录结构:
./
├── conf.d
│ └── default.conf
├── dist
├── edu.config.js
└── start.sh
startup.sh
docker stop edu-frontend
docker rm edu-frontend
docker run -d --name edu-frontend \
-p 8070:80 \
-v /root/education/study/frontend/dist:/usr/share/nginx/html \
-v /root/education/study/frontend/conf.d:/etc/nginx/conf.d \
-v /root/education/study/frontend/edu.config.js:/usr/share/nginx/html/edu.config.js \
nginx
部署MySQL
#
docker pull mysql:8.4
# 运行容器
docker run -d \
--name mysql8 \
-p 3306:3306 \
--privileged \
--restart=always \
-v E:/var/mysql8/conf/my.cnf:/etc/mysql/my.cnf \
-v E:/var/mysql8/logs:/logs \
-v E:/var/mysql8/data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=123 \
mysql:8.4
README
作者:银法王
版权声明:本文遵循知识共享许可协议3.0(CC 协议): 署名-非商业性使用-相同方式共享 (by-nc-sa)
修改历史:
2020-03-15 第一次修订
2021-12-22 修改
2023-06-23 完善
参考: