容器技术Docker
容器技术Docker
Docker 先启动一个容器也需要一个外部模板,也称为镜像,docke的镜像可以保存在一个公共的地方共享使用,只要把镜像下载下来就可以使用,最主要的是可以在镜像基础之上做自定义配置并且可以再把其提交为一个镜像,一个镜像可以被启动为多个容器。
Docker的镜像是分层的,镜像底层为库文件且只读层即不能写入也不能删除数据,从镜像加载启动为一个容器后会生成一个可写层,其写入的数据会复制到宿主机上对应容器的目录,但是容器内的数据在删除容器后也会被随之删除。
Docker 官网: http://www.docker.com
帮助文档链接: https://docs.docker.com/
Docker 镜像: https://hub.docker.com/
Docker 中文网站: http://www.docker.org.cn/
docker组成
Docker 主机(Host): 一个物理机或虚拟机,用于运行Docker服务进程和容器,也称为宿主机,
node节点
Docker 服务端(Server): Docker守护进程,运行docker容器 docker engine
Docker 客户端(Client): 客户端使用 docker 命令或其他工具调用docker API
Docker 镜像(Images): 镜像可以理解为创建实例使用的模板,本质上就是一些程序文件的集合
Docker 仓库(Registry): 保存镜像的仓库,官方仓库: https://hub.docker.com/,可以搭建私有仓库
harbor
Docker 容器(Container): 容器是从镜像生成对外提供服务的一个或一组服务,其本质就是将镜像中的程序启动后生成的进程

docker的优势
-
快速部署: 短时间内可以部署成百上千个应用,更快速交付到线上
-
高效虚拟化: 不需要额外hypervisor支持,基于linux内核实现应用虚拟化,相比虚拟机大幅提高性能和效率
-
节省开支: 提高服务器利用率,降低IT支出
-
简化配置: 将运行环境打包保存至容器,使用时直接启动即可
-
环境统一: 将开发,测试,生产的应用运行环境进行标准化和统一,减少环境不一样带来的各种问题
-
快速迁移和扩展: 可实现跨平台运行在物理机、虚拟机、公有云等环境,良好的兼容性可以方便将应用从A宿主机迁移到B宿主机,甚至是A平台迁移到B平台
-
更好的实现面向服务的架构,推荐一个容器只运行一个应用,实现分布的应用模型,可以方便的进行横向扩展,符合开发中高内聚,低耦合的要求,减少不同服务之间的相互影响
docker的缺点
-
多个容器共用宿主机的内核,各应用之间的隔离不如虚拟机彻底
-
由于和宿主机之间的进程也是隔离的,需要进入容器查看和调试容器内进程等资源,变得比较困难和繁琐
-
如果容器内进程需要查看和调试,需要在每个容器内都需要安装相应的工具,这也造成存储空间的重复浪费
docker的运行机制

docker安装
官方网址: https://www.docker.com/
官方安装docker

阿里云文档: https://developer.aliyun.com/mirror/docker-ce?spm=a2c6h.13651102.0.0.3e221b11guHCWE

安装成功后查看docker状态

查看docker安装的版本

docker命令帮助,执行docker --help


查看docker0网卡
4: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 8e:10:b1:ae:1b:db brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
[qwe@ubuntu-134 ~]$ route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
172.17.0.0 0.0.0.0 255.255.0.0 U 0 0 0 docker0
docker配置和优化
支持官方仓库和私有仓库镜像下载,目的是加快下载速度,默认用的是官方镜像加速器,可以换成阿里、清华园的镜像加速器
[qwe@ubuntu-134 ~]$ cat /etc/docker/daemon.json
{
"registry-mirrors": [
"https://docker.m.daocloud.io",
"https://docker.1panel.live",
"https://docker.1ms.run",
"https://docker.xuanyuan.me"
],
"insecure-registries": ["harbor.wang.org"]
}
docker镜像管理
镜像即创建容器的模版,含有启动容器所需要的文件系统及所需要的内容,因此镜像主要用于方便和快速的创建并启动容器
镜像含里面是一层层的文件系统,叫做 Union FS(联合文件系统),联合文件系统,可以将几层目录挂载到一起(就像千层饼,洋葱头,俄罗斯套娃一样),形成一个虚拟文件系统,虚拟文件系统的目录结构就像普通 linux 的目录结构一样,镜像通过这些文件再加上宿主机的内核共同提供了一个 linux 的虚拟环境,每一层文件系统叫做一层 layer,联合文件系统可以对每一层文件系统设置三种权限,只读(readonly)、读写(readwrite)和写出(whiteout-able),但是镜像中每一层文件系统都是只读的,构建镜像的时候,从一个最基本的操作系统开始,每个构建提交的操作都相当于做一层的修改,增加了一层文件系统,一层层往上叠加,上层的修改会覆盖底层该位置的可见性,这也很容易理解,就像上层
把底层遮住了一样,当使用镜像的时候,我们只会看到一个完全的整体,不知道里面有几层,实际上也不需要知道里面有几层。
查看镜像的分层结构
[root@ubuntu2404 ~]#docker pull nginx
Using default tag: latest
latest: Pulling from library/nginx
8ec398bc0356: Pull complete
a53c868fbde7: Pull complete
79daf9dd140d: Pull complete
Digest: sha256:70821e443be75ea38bdf52a974fd2271babd5875b2b1964f05025981c75a6717
Status: Downloaded newer image for nginx:latest
docker.io/library/nginx:latest
镜像仓库
-
Docker hub: docker官方的公共仓库,已经保存了大量的常用镜像,可以方便大家直接使用
-
阿里云,网易等第三方镜像的公共仓库
-
Image registry: docker 官方提供的私有仓库部署工具,无web管理界面,目前使用较少
-
Harbor: vmware 提供的自带web界面自带认证功能的镜像私有仓库,目前有很多公司使用
搜索镜像
docker官网:
http://hub.docker.com
http://dockerhub.com
https://hub-stage.docker.com/ #无需科学上网
执行docker search命令进行搜索
格式如下
[root@ubuntu-134 ~]# docker search --help
Usage: docker search [OPTIONS] TERM
Search Docker Hub for images
Options:
-f, --filter filter Filter output based on conditions provided
--format string Pretty-print search using a Go template
--limit int Max number of search results
--no-trunc Don't truncate output
alpine 管理软件
/ # cat /etc/apk/repositories
https://dl-cdn.alpinelinux.org/alpine/v3.15/main
https://dl-cdn.alpinelinux.org/alpine/v3.15/community
#修改源替换成国内源
sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/' /etc/apk/repositories
sed -i 's/dl-cdn.alpinelinux.org/mirrors.tuna.tsinghua.edu.cn/'
/etc/apk/repositories
sed -i 's/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/' /etc/apk/repositories
#更新源
apk update #相当于 apt update
#安装软件
apk add vim#相当于 apt install vim
#删除软件
apk del openssh openntp vim #相当于 apt remove openssh
#安装常见软件
apk update && apk --no-cache add bash curl telnet wget net-tools pstree zip
unzip
#安装常用编译工具
apk update && apk --no-cache add gcc make curl zip unzip net-tools pstree wget
libgcc libc-dev libcurl libc-utils pcre-dev zlib-dev libnfs pcre pcre2 libevent
libevent-dev iproute2
#修改时区
apk update && apk --no-cache add tzdata && ln -s
/usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo "Asia/Shanghai" > /etc/timezone
下载镜像
从 docker 仓库将镜像下载到本地,命令格式如下:
[root@ubuntu-134 ~]# docker pull --help
Usage: docker pull [OPTIONS] NAME[:TAG|@DIGEST]
NAME: 是镜像名,格式:仓库服务器:端口/项目名称/镜像名称,仓库服务器:端口/项目名称/可以省略,默认
docker.io/library/
TAG: 即版本号,如果不指定:TAG,则下载最新版镜像,即latest
默认镜像下载保存的路径:
#29.X版本以后路径
/var/lib/docker/containerd/daemon
#旧版路径
/var/lib/docker/overlay2/镜像ID
查看本地镜像
docker images 可以查看下载至本地的镜像
格式:
docker images [OPTIONS] [REPOSITORY[:TAG]]
docker image ls [OPTIONS] [REPOSITORY[:TAG]]
REPOSITORY #镜像所属的仓库名称
TAG #镜像版本号(标识符),默认为latest
IMAGE ID #镜像唯一ID标识,如果ID相同,说明是同一个镜像有多个名称
CREATED #镜像在仓库中被创建时间
VIRTUAL SIZE #镜像的大小
示例
[root@ubuntu-134 ~]# docker images
IMAGE ID DISK USAGE CONTENT SIZE EXTRA
alpine:latest 25109184c71b 13.1MB 3.95MB
hello-world:latest f9078146db2e 25.9kB 9.49kB
tomcat:latest 0935005185c6 588MB 158MB U
范例: 查看指定镜像的详细信息
[root@ubuntu-134 ~]# docker inspect alpine:latest
[
{
"Id": "sha256:25109184c71bdad752c8312a8623239686a9a2071e8825f20acb8f2198c3f659",
"RepoTags": [
"alpine:latest"
],
"RepoDigests": [
"alpine@sha256:25109184c71bdad752c8312a8623239686a9a2071e8825f20acb8f2198c3f659"
],
"Comment": "buildkit.dockerfile.v0",
"Created": "2026-01-28T01:18:04.977843834Z",
"Config": {
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
],
"Cmd": [
"/bin/sh"
],
"WorkingDir": "/"
},
"Architecture": "amd64",
"Os": "linux",
"Size": 3872672,
"RootFS": {
"Type": "layers",
"Layers": [
"sha256:989e799e634906e94dc9a5ee2ee26fc92ad260522990f26e707861a5f52bf64e"
]
},
"Metadata": {
"LastTagTime": "2026-04-15T03:01:28.835522418Z"
},
"Descriptor": {
"mediaType": "application/vnd.oci.image.index.v1+json",
"digest": "sha256:25109184c71bdad752c8312a8623239686a9a2071e8825f20acb8f2198c3f659",
"size": 9218
},
"Identity": {
"Pull": [
{
"Repository": "docker.io/library/alpine"
}
]
}
}
]
镜像导出
利用docker save命令可以将从本地镜像导出为一个打包 tar文件,然后复制到其他服务器进行导入使用
注意:镜像导出支持多个镜像导出
格式:
docker save [OPTIONS] IMAGE [IMAGE...]
选项:
-o, --output string Write to a file, instead of STDOUT
#说明:
Docker save 使用IMAGE ID导出,在导入后的镜像没有REPOSITORY和TAG,显示为<none>
常见用法
#导出为tar格式
docker save -o /path/file.tar IMAGE1 IMAGE2 ...
docker save IMAGE1 IMAGE2 ... > /path/file.tar
#导出为压缩格式
docker save IMAGE1 IMAGE2 ... | gzip > /path/file.tar.gz
范例:导出指定镜像
[root@ubuntu2404 ~]#docker images
REPOSITORY TAG IMAGE ID CREATED
SIZE
nginx latest 5ad3bd0e67a9 3 days ago
127MB
alpine 3.11.3 e7d92cdc71fe 7 days ago
5.59MB
centos centos8.1.1911 470671670cac 7 days ago
237MB
centos latest 470671670cac 7 days ago
237MB
mysql 5.6.47 742f7d5a4104 10 days ago
302MB
mysql 5.7.29 b598110d0fff 10 days ago
435MB
busybox latest 6d5fcfe5ff17 4 weeks ago
1.22MB
hello-world latest fce289e99eb9 12 months ago
1.84kB
[root@ubuntu2404 ~]#docker save mysql:5.7.30 alpine:3.11.3 -o /data/myimages.tar
#或者
[root@ubuntu2404 ~]#docker save mysql:5.7.30 alpine:3.11.3 > /data/myimages.tar
[root@ubuntu2404 ~]#scp /data/myimages.tar 10.0.0.7:/data
范例:导出镜像并压缩
[root@ubuntu2404 ~]#docker save rockylinux:9.1-minimal | gzip - > rockylinux-9.1-minimal.tar.gz
[root@ubuntu2404 ~]#ll rockylinux-9.1-minimal.tar.gz -h
-rw------- 1 root root 44M 12月 30 09:33 rockylinux-9.1-minimal.tar.gz
范例:导出所有镜像到一个打包文件
#方法1: 使用image ID导出镜像,在导入后的镜像没有REPOSITORY和TAG,显示为<none>
[root@ubuntu2404 ~]#docker save `docker images -qa` -o all.tar
#方法2:将所有镜像导入到一个文件中,此方法导入后可以看REPOSITORY和TAG
[root@ubuntu2404 ~]#docker save `docker images | awk 'NR!=1{print $1":"$2}'` -o all.tar
[root@ubuntu2404 ~]#docker save `docker images | awk 'NR!=1{print $1":"$2}'` | gzip > all.tar.gz
#方法3:将所有镜像导入到一个文件中,此方法导入后可以看REPOSITORY和TAG
[root@ubuntu2404 ~]#docker image save `docker image ls --format "{{.Repository}}:{{.Tag}}"` -o all.tar
[root@ubuntu2404 ~]#docker image save `docker image ls --format "{{.Repository}}:{{.Tag}}"` | gzip>all.tar.gz
镜像导入
利用docker load命令可以将镜像导出的打包或压缩文件再导入
注意:镜像导入只能支持单个镜像导入,不支持多个镜像导入
格式:
docker load [OPTIONS]
#选项
-i, --input string Read from tar archive file, instead of STDIN
-q, --quiet Suppress the load output
常见用法
docker load -i /path/file.tar
docker load < /path/file.tar.gz
删除镜像
docker rmi 命令可以删除本地镜像
格式:
docker rmi [OPTIONS] IMAGE [IMAGE...]
docker image rm [OPTIONS] IMAGE [IMAGE...]
#选项:
-f, --force Force removal of the image
--no-prune Do not delete untagged parents
范例: 删除所有镜像
[root@ubuntu2404 ~]#docker rmi -f `docker images -q`
Deleted: sha256:470671670cac686c7cf0081e0b37da2e9f4f768ddc5f6a26102ccd1c6954c1ee
Deleted: sha256:0683de2821778aa9546bf3d3e6944df779daba1582631b7ea3517bb36f9e4007
Untagged: mysql:5.6.47
容器管理
容器相关命令
[root@ubuntu-134 ~]# docker container
Usage: docker container COMMAND
Manage containers
Commands:
attach Attach local standard input, output, and error streams to a running container
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
exec Execute a command in a running container
export Export a container's filesystem as a tar archive
inspect Display detailed information on one or more containers
kill Kill one or more running containers
logs Fetch the logs of a container
ls List containers
pause Pause all processes within one or more containers
port List port mappings or a specific mapping for the container
prune Remove all stopped containers
rename Rename a container
restart Restart one or more containers
rm Remove one or more containers
run Create and run a new container from an image
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
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
wait Block until one or more containers stop, then print their exit codes
Run 'docker container COMMAND --help' for more information on a command.
启动容器
docker run 可以启动容器,进入到容器,并随机生成容器ID和名称
启动第一个运行的容器
范例: 运行docker 的 hello world
[root@ubuntu-134 ~]# docker run hello-world:latest
Hello from Docker!
This message shows that your installation appears to be working correctly.
To generate this message, Docker took the following steps:
1. The Docker client contacted the Docker daemon.
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
(amd64)
3. The Docker daemon created a new container from that image which runs the
executable that produces the output you are currently reading.
4. The Docker daemon streamed that output to the Docker client, which sent it
to your terminal.
To try something more ambitious, you can run an Ubuntu container with:
$ docker run -it ubuntu bash
Share images, automate workflows, and more with a free Docker ID:
https://hub.docker.com/
For more examples and ideas, visit:
https://docs.docker.com/get-started/
[root@ubuntu-134 ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
aed7bc1d4c8b hello-world:latest "/hello" 42 seconds ago Exited (0) 42 seconds ago thirsty_mcnulty
启动容器的流程

启动容器的用法
命令格式:
docker run [选项] [镜像名] [shell命令] [参数]
#选项:
-i, --interactive Keep STDIN open even if not attached,通常和-t一起使用
-t, --tty 分配pseudo-TTY,通常和-i一起使用,注意对应的容器必须运行shell才支持进
入
-d, --detach Run container in background and print container ID,台后运行,默认前台
--name string Assign a name to the container
--h, --hostname string Container host name
--rm Automatically remove the container when it exits,注意:此选项会自动删除匿名卷
-p, --publish list Publish a container's port(s) to the host
-P, --publish-all Publish all exposed ports to random ports
--dns list Set custom DNS servers
--entrypoint string Overwrite the default ENTRYPOINT of the image
--restart policy
--privileged Give extended privileges to container
-e, --env=[] Set environment variables
--env-file=[] Read in a line delimited file of environment variables
--sysctl net.ipv4.ip_unprivileged_port_start=0 #指定容器的内核参数,但不修改宿主机内核
--ulimit ulimit #指定ulimit限制配置,比如: --ulimit nofile=10240:10240
[shell命令] [参数] #使用指定的命令和参数,替换容器默认的命令
范例: 一次性运行容器,退出后立即删除,用于测试
[root@ubuntu2404 ~]#docker run --rm alpine cat /etc/issue
Welcome to Alpine Linux 3.11
Kernel \r on an \m (\l)
[root@ubuntu2404 ~]#docker ps -a
CONTAINER ID IMAGE COMMAND CREATED
STATUS PORTS NAMES
范例: 开机自动运行容器
#默认容器不会自动启动,设置容器总是运行
[root@ubuntu2404 ~]#docker run -d --name nginx --restart=always -p 80:80 nginx
[root@ubuntu2404 ~]#reboot
[root@ubuntu2404 ~]#docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
NAMES
dbdba90076e1 nginx"nginx -g 'daemon of…" About a minute agoUp 49
seconds0.0.0.0:80->80/tcp nginx
[root@ubuntu2404 ~]#docker run -d -p 4000:4000 docs/docker.github.io:latest
[root@ubuntu2404 ~]#docker images docs/docker.github.io
REPOSITORY TAG IMAGE ID CREATED SIZE
docker.io/docs/docker.github.io latest ffd9131eeee7 2 days ago 1.99 GB
#用浏览器访问http://localhost:4000/可以看到下面docker文档资料
范例: 运行docker官方文档容器

查看容器信息
显示当前存在的容器
https://docs.docker.com/engine/reference/commandline/ps/
格式
docker ps [OPTIONS]
docker container ls [OPTIONS]
选项:
-a, --all Show all containers (default shows just running)
-q, --quiet Only display numeric IDs
-s, --size Display total file sizes
-f, --filter filter Filter output based on conditions provided
-l, --latest Show the latest created container (includes all states)
-n, --last int Show n last created containers (includes all states)
(default -1)
--format 按格式输出信息
查看容器内的进程
docker top CONTAINER [ps OPTIONS]
示例
[root@ubuntu2404 ~]#docker top 9997
UID PID PPID C
STIME TTY TIME CMD
root 10023 9997 3
22:03 ? 00:00:00 /bin/sh -c i=1;while
true;do echo hello$i;let i++;sleep 1;done
root 10074 10023 0
22:03 ? 00:00:00 sleep 1
范例: 查看容器的监听端口
[root@node1 ~]#docker run -d --name myapp registry.cnbeijing.aliyuncs.com/wangxiaochun/nginx:1.24.0
[root@node1 ~]#docker top myapp
UID PID PPID C
STIME TTY TIME CMD
root 70721 70700 1
12:51 ? 00:00:00 nginx: master
process nginx -g daemon off;
systemd+ 70763 70721 0
12:51 ? 00:00:00 nginx: worker
process
systemd+ 70764 70721 0
12:51 ? 00:00:00 nginx: worker
process
[root@node1 ~]#nsenter -t 70721 -n ss -tlnp
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
LISTEN 0 511 0.0.0.0:80 0.0.0.0:* users:
(("nginx",pid=70764,fd=6),("nginx",pid=70763,fd=6),("nginx",pid=70721,fd=6))
LISTEN 0 511 [::]:80 [::]:* users:
(("nginx",pid=70764,fd=7),("nginx",pid=70763,fd=7),("nginx",pid=70721,fd=7))
查看容器资源使用情况
docker stats [OPTIONS] [CONTAINER...]
范例
[root@ubuntu2404 ~]#docker stats 251c7c7cf2aa
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O
PIDS
251c7c7cf2aa busy_l0.00% 3.742MiB / 1.924GiB 0.19% 1.29kB / 0B0B / 8.19kB
2
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O
PIDS
251c7c7cf2aa busy_l0.00% 3.742MiB / 1.924GiB 0.19% 1.29kB / 0B0B / 8.19kB
#查看所有容器
[root@ubuntu2404 ~]#docker stats
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
5e470e7970f6 suspi 0.00% 3.992MiB / 1.924Gi0.20% 656B / 0B9.2MB / 8.19kB 2
829bcebbc9f6 elast 0.58% 1.24GiB / 1.924GiB64.43%2.97kB / 512kB / 729kB 47
查看容器的详细信息
docker inspect 可以查看docker各种对象的详细信息,包括:镜像,容器,网络等
docker inspect [OPTIONS] NAME|ID [NAME|ID...]
Options:
-f, --format string Format the output using the given Go template
-s, --size Display total file sizes if the type is container
示例
[root@ubuntu2404 ~]#docker inspect nginx
查看容器的日志
docker logs 可以查看容器中运行的进程在控制台的标准输出和标准错误,一般对应是日志信息
docker 日志是存放在宿主机的 /var/lib/docker/containers/<container_id>/<container_id>-json.log文件中
[root@ubuntu-134 ~]# docker logs --help
Usage: docker logs [OPTIONS] CONTAINER
Fetch the logs of a container
Aliases:
docker container logs, docker logs
Options:
--details Show extra details provided to logs
-f, --follow Follow log output
--since string Show logs since timestamp (e.g. "2013-01-02T13:23:37Z") or relative (e.g. "42m" for 42 minutes)
-n, --tail string Number of lines to show from the end of the logs (default "all")
-t, --timestamps Show timestamps
--until string Show logs before a timestamp (e.g. "2013-01-02T13:23:37Z") or relative (e.g. "42m" for 42 minutes)
查看容器日志
[root@ubuntu2404 ~]#docker logs 5126
hello1
hello2
hello3
hello4
hello5
hello6
#显示时间
[root@ubuntu2404 ~]#docker logs --tail 0 -t 5126
2020-02-25T13:30:07.321390731Z hello17
#持续跟踪
[root@ubuntu2404 ~]#docker logs -f 5126
删除容器
docker rm 可以删除容器,即使容器正在运行当中,也可以被强制删除掉
格式
docker rm [OPTIONS] CONTAINER [CONTAINER...]
docker container rm [OPTIONS] CONTAINER [CONTAINER...]
#选项:
-f, --force Force the removal of a running container (uses SIGKILL)
-v, --volumes Remove the volumes associated with the container
删除所有容器
[root@ubuntu2404 ~]#docker rm -f `docker ps -a -q`
df428caf7128
6d64f47a83e6
edd2ac2690e6
容器的启动和停止
格式
docker start|stop|restart|pause|unpause 容器ID
启动并进入容器
#启动并进入容器
[root@ubuntu2404 ~]#docker start -i c1
root@539722b55b76:/# exit
exit
进入正在运行的容器
exec命令
在运行中的容器启动新进程,可以执行单次命令,以及进入容器
格式
docker exec [OPTIONS] CONTAINER COMMAND [ARG...]
常用选项:
-d, --detach Detached mode: run command in the background
-e, --env list Set environment variables
-i, --interactive Keep STDIN open even if not attached
-t, --tty Allocate a pseudo-TTY
-u, --user string Username or UID
#常见用法
docker exec -it -uroot 容器ID sh|bash
暴露所有容器端口
容器启动后,默认处于预定义的NAT网络中,所以外部网络的主机无法直接访问容器中网络服务docker run -P 可以将事先容器预定义的所有端口映射宿主机的网卡的随机端口,默认从32768开始使用随机端口 时,当停止容器后再启动可能会导致端口发生变化
-P , --publish-all= true | false默认为false
#示例:
docker run -P docker.io/nginx #映射容器所有暴露端口至随机本地端口
指定端口映射
docker run -p 可以将容器的预定义的指定端口映射到宿主机的相应端口
注意: 多个容器映射到宿主机的端口不能冲突,但容器内使用的端口可以相同
方式1: 容器80端口映射宿主机本地随机端口
docker run -p 80 --name nginx-test-port1 nginx
方式2: 容器80端口映射到宿主机本地端口81
docker run -p 81:80 --name nginx-test-port2 nginx
方式3: 宿主机本地IP:宿主机本地端口:容器端口
docker run -p 10.0.0.100:82:80 --name nginx-test-port3 docker.io/nginx
方式6: 一次性映射多个端口+协议
docker run -p 8080:80/tcp -p 8443:443/tcp -p 53:53/udp --name nginx-test-port6 nginx
范例
[root@ubuntu2404 ~]#docker run -d -p 8080:80 -p 8443:443 -p 8053:53/udp nginx
a902b177bb7135ad8a8a179dbf8ce02dcc4806a1136475e59c2310833d7434ab
[root@ubuntu2404 ~]#docker ps
CONTAINER ID IMAGE COMMAND CREATED
STATUS PORTS
NAMES
a902b177bb71 nginx "nginx -g 'daemon of…" 5 seconds ago
Up 4 seconds 0.0.0.0:8053->53/udp, 0.0.0.0:8080->80/tcp, 0.0.0.0:8443->443/tcp affectionate_aryabhata
范例:查看端口映射关系
[root@ubuntu2404 ~]#docker run --name nginx01 -P -d nginx:1.20
[root@ubuntu2404 ~]#docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS
PORTS NAMES
63d61635e8a4 nginx:1.20 "/docker-entrypoint.…" 10 seconds ago Up 9
seconds 0.0.0.0:49153->80/tcp, :::49153->80/tcp nginx01
[root@ubuntu2404 ~]#docker port nginx01
80/tcp -> 0.0.0.0:49153
80/tcp -> :::49153
定制容器内部的hosts文件
容器会自动将容器的ID加入自已的/etc/hosts文件中,并解析成容器的IP,可以定制容器的hosts文件
docker run --add-host www.wangxiaochun.com:6.6.6.6
范例
[root@ubuntu2404 ~]#docker run -it centos /bin/bash
[root@598262a87c46 /]# cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.2 598262a87c46 #默认会将实例的ID 添加到自己的hosts文件
[root@598262a87c46 /]# hostname
598262a87c46
[root@598262a87c46 /]# ping 598262a87c46
PING 598262a87c46 (172.17.0.2) 56(84) bytes of data.
64 bytes from 598262a87c46 (172.17.0.2): icmp_seq=1 ttl=64 time=0.118 ms
64 bytes from 598262a87c46 (172.17.0.2): icmp_seq=2 ttl=64 time=0.085 ms
范例: 修改容器的 hosts文件
[root@ubuntu2404 ~]#docker run -it --rm --add-host www.wangsi.com:6.6.6.6 --add-host www.wang.org:8.8.8.8 busybox
/ # cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
6.6.6.6 www.wangsi.com
8.8.8.8 www.wang.org
172.17.0.2 449bf0468efd
指定容器DNS
容器的dns服务器,默认采用宿主机的dns 地址
注意:如果当前主机为DNS服务器,则网卡配置指向本机的IP而非127.0.0.1,否则会造成此主机的上的
Docker 容器无法获取宿主机的DNS地址配置
可以用下面方式指定其它的DNS地址
-
修改宿主机的DNS地址址配置
-
在容器启动时加选项 --dns=x.x.x.x
-
在/etc/docker/daemon.json 文件中指定
-
修改service文件中 dockerd --dns
范例: 指定DNS地址
[root@ubuntu2404 ~]#docker run -it --rm --dns 1.1.1.1 --dns 8.8.8.8 centos bash
[root@ef9cacc74b58 /]# cat /etc/resolv.conf
search wang.com wang.org
nameserver 1.1.1.1
nameserver 8.8.8.8
[root@ef9cacc74b58 /]# exit
exit
容器内和宿主机之间复制文件
不论容器的状态是否运行,复制都可以实现
docker cp [OPTIONS] CONTAINER:SRC_PATH DEST_PATH|-
docker cp [OPTIONS] SRC_PATH|- CONTAINER:DEST_PATH
Options:
-a, --archive Archive mode (copy all uid/gid information)
-L, --follow-link Always follow symbol link in SRC_PATH
范例: 复制容器的文件至宿主机
[root@ubuntu2404 ~]#docker run -it --name b1 busybox sh
[root@ubuntu2404 ~]#docker cp b1:/bin/busybox /usr/local/bin/
[root@ubuntu2404 ~]#busybox ls
范例
#将容器内文件复制到宿主机
[root@ubuntu2404 ~]#docker cp -a 1311:/etc/centos-release .
[root@ubuntu2404 ~]#cat centos-release
CentOS Linux release 8.1.1911 (Core)
#将宿主机文件复制到容器内
[root@ubuntu2404 ~]#docker cp /etc/issue 1311:/root/
[root@ubuntu2404 ~]#docker exec 1311 cat /root/issue
Ubuntu 18.04.1 LTS \n \l
导出和导出容器文件系统
docker export 和 docker save 都可以用于将 Docker 的容器/镜像导出到本地文件系统,但是它们用途和效果是不同的
docker export:
容器 --> docker export --> tar file 文件系统打包文件 --> docker import --> 新镜像(相对原始镜像丢失一些属性:比如:环境变量,CMD)
此命令是用于将一个运行的或者停止的容器的文件系统导出为一个 tar 归档文件。需要注意的是,docker export 不会包含该容器的历史(也就是每个层的变更),并且也不会包含容器的环境变量、元数据和其他相关的配置信息。这意味着如果你导入一个用 docker export 导出的 tar 文件并运行,你得到的将是一个新的、干净的容器,没有之前容器的运行历史和配置(比如:默认的启动命令会丢失)。
docker save:
原镜像 --> docker save --> tar file 镜像格式的文件 --> docker load --> 原镜像
此命令用于将一个或多个镜像导出为一个 tar 归档文件。与 docker export 不同, docker save 会完整地保存镜像的所有内容,包括每一层的变更、所有的元数据、所有的标签等。这意味着如果你导入一个用 docker save 导出的 tar 文件并运行,你得到的将是一个与原镜像完全一样的新镜像,包括所有的历史和配置。
范例
[root@ubuntu2404 ~]#docker export nginx -o nginx.tar
[root@ubuntu2404 ~]#tar tvf nginx.tar |head
-rwxr-xr-x 0/0 0 2022-07-06 17:45 .dockerenv
drwxr-xr-x 0/0 0 2021-12-20 08:00 bin/
#import 实现将容器文件生成镜像
[root@ubuntu2404 ~]#docker import nginx.tar nginx:v1.22
[root@ubuntu2404 ~]#docker images nginx:v1.22
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx test ca611fd77d08 6 minutes ago 140MB
查看docker run启动参数命令
忘记之前启动一个容器的启动命令是什么,现在需要找回来 docker run 的运行参数,可以使用 runlike 工具实现
https://github.com/lavie/runlike
安装 runlike
#安装方式1: pip
apt install -y python3-pip
pip3 install runlike
#安装方法2: by docker
alias runlike="docker run --rm -v /var/run/docker.sock:/var/run/docker.sock assaflavie/runlike"
范例
#包安装
[root@ubuntu2404 ~]#apt install -y python3-pip
[root@ubuntu2404 ~]#pip3 install runlike --break-system-packages
[root@ubuntu2404 ~]#apt install -y python3-pip
[root@ubuntu2404 ~]#pip3 install runlike
#启动一个测试容器
[root@ubuntu2404 ~]#docker run -e MYSQL_ROOT_PASSWORD=123456 -e
MYSQL_DATABASE=wordpress -e MYSQL_USER=wordpress -e MYSQL_PASSWORD=123456 --name
mysql -d -v /data/mysql:/var/lib/mysql --restart=always registry.cnbeijing.aliyuncs.com/wangxiaochun/mysql:8.0.29-oracle
#查看容器运行命令
[root@ubuntu2404 ~]#runlike -p mysql
docker run --name=mysql \
--hostname=7c0f6ba11f5a \
--mac-address=02:42:ac:11:00:02 \
--env=MYSQL_ROOT_PASSWORD=123456 \
--env=MYSQL_DATABASE=wordpress \
--env=MYSQL_USER=wordpress \
--env=MYSQL_PASSWORD=123456 \
--volume=/data/mysql:/var/lib/mysql \
--expose=3306 \
--expose=33060 \
--restart=always \
--runtime=runc \
--detach=true \
mysql:8.0.29-oracle \
mysqld
Docker镜像制作
镜像为了更小和运行效率,镜像中是不包含内核的,而使用宿主机的内核镜像本身则只提供应用所依赖的根文件系统和相关文件,即系统运行所必要的文件目录,比如: /sys, /dev/,/proc,/bin,/etc等目录基于内核的名称空间实现容器的各种资源隔离
利用DockerFile文件执行docker build自动构建镜像
DockerFile 是一种被Docker程序解释执行的脚本,由一条条的命令组成的,每条命令对应linux下面的一条命令,Docker程序将这些DockerFile指令再翻译成真正的linux命令,其有自己的书写方式和支持的命令,Docker程序读取DockerFile并根据指令生成Docker镜像,相比手动制作镜像的方式,DockerFile更能直观的展示镜像是怎么产生的,有了DockerFile,当后期有额外的需求时,只要在之前的
DockerFile添加或者修改响应的命令即可重新生成新的Docker镜像,避免了重复手动制作镜像的麻烦,类似与shell脚本一样,可以方便高效的制作镜像
dockerfile 官方说明:
https://docs.docker.com/engine/reference/builder/

dockerfile 文件中的有18个指令,但最常见指令
FROM
LABEL
RUN
ADD
COPY
CMD
ENTRYPOINT
ENV
EXPOSE
USER
VOLUME
WORKDIR
FROM: 指定基础镜像
定制镜像,需要先有一个基础镜像,在这个基础镜像上进行定制。
FROM 就是指定基础镜像,此指令通常必需放在Dockerfile文件第一个非注释行。后续的指令都是运行于此基准镜像所提供的运行环境
范例:
FROM scratch #所有镜像的起源镜像,相当于JAVA中Object类
FROM ubuntu
FROM ubuntu:bionic
FROM debian:buster-slim
RUN:执行shell命令
RUN 指令用来在构建镜像阶段需要执行 FROM 指定镜像所支持的Shell命令。通常各种基础镜像一般都支持丰富的shell命令
注意: RUN 可以写多个,每一个RUN指令都会建立一个镜像层,所以尽可能合并成一条指令,比如将多个shell命令通过 && 连接一起成为在一条指令
每个RUN都是独立运行的,和前一个RUN无关
#shell 格式: 相当于 /bin/sh -c <命令> 此种形式支持环境变量
RUN <命令>
#如果想使用其它shell,可以用SHELL指令指定不同的shell
SHELL ["/bin/bash", "-c"]
RUN <命令>
#示例
SHELL ["/bin/bash", "-c"]
RUN echo {1..10}
范例
RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html
RUN ["/bin/bash", "-c", "echo hello world"]
RUN yum -y install epel-release \
&& yum -y install nginx \
&& rm -rf /usr/share/nginx/html/*
&& echo "<h1> docker test nginx </h1>" > /usr/share/nginx/html/index.html
ENV:设置环境变量
ENV 可以定义环境变量和值,会被后续指令(如:ENV,ADD,COPY,RUN等)通过KEY或KEY或KEY或{KEY}进行引用,并在容器运行时保持
#变量赋值格式1
ENV <key> <value> #此格式只能对一个key赋值,<key>之后的所有内容均会被视作其<value>的组成
部分
#变量赋值格式2
ENV <key1>=<value1> <key2>=<value2> \ #此格式可以支持多个key赋值,定义多个变量建议使用,
减少镜像层
<key3>=<value3> ...
#如果<value>中包含空格,可以以反斜线\进行转义,也可通过对<value>加引号进行标识;另外,反斜线也
可用于续行
#示例
ENV JAVA_OPS=""
范例
ENV VERSION=1.0 DEBUG=on NAME="Happy Feet"
ENV PG_MAJOR 9.3
ENV PG_VERSION 9.3.4
RUN curl -SL http://example.com/postgres-$PG_VERSION.tar.xz | tar -xJC
/usr/src/postgress && …
ENV PATH /usr/local/postgres-$PG_MAJOR/bin:$PATH
COPY:复制文本
复制本地宿主机的 到镜像中的
COPY [OPTIONS] [--chown=<user>:<group>] <src>... <dest>
COPY [OPTIONS] [--chown=<user>:<group>] ["<src>",... "<dest>"] #路径中有空白字符时,
建议使用此格式
范例
COPY hom* /mydir/
COPY hom?.txt /mydir/
#多阶段构建
COPY --from=build /myapp /usr/bin/
ADD:复制和解包文件
ADD 指令具备 COPY 的基本复制功能,此外还增加了一些特殊特性。
ADD 指令的特殊之处在于:
-
源路径可以是远程 URL,它会自动下载文件并复制到镜像中,如果是打包文件不会自动解压缩。
-
如果源路径是一个压缩文件(如 tar、gzip、bzip2 等),它会自动解压后再复制到镜像中。
格式
ADD [--chown=<user>:<group>] <src>... <dest>
ADD [--chown=<user>:<group>] ["<src>",... "<dest>"]
范例
ADD test relativeDir/ # adds "test" to `WORKDIR`/relativeDir/
ADD test /absoluteDir/ # adds "test" to /absoluteDir/
ADD --chown=55:mygroup files* /somedir/
ADD --chown=bin files* /somedir/
ADD --chown=1 files* /somedir/
ADD --chown=10:11 files* /somedir/
ADD ubuntu-xenial-core-cloudimg-amd64-root.tar.gz /
ADD nginx-1.26.2.tar.gz /usr/local/src
RUN apk --no-cache add gcc make libgcc libc-dev libcurl libc-utils pcre-dev
zlib-dev libnfs pcre pcre2 libevent libevent-dev && cd /usr/local/src/nginx-
1.26.2 && ./configure --prefix=/apps/nginx && make && make install && rm -rf
/usr/local/src/nginx-1.26.2
CMD:容器启动命令

CMD 用来指定启动容器时默认执行的一个初始命令
如果容器内没有一个持续运行的前台进程,容器会停止
所以一般CMD 指定的命令为持续运行且为前台命令,如果有多个命令,需要保证有一个命令是前台并持续运行的
-
如果docker run没有指定任何的执行命令或者dockerfile里面也没有ENTRYPOINT命令,那么开启
-
容器时就会使用执行CMD指定的默认的命令
-
RUN 命令是在构建镜像时执行的命令
-
每个 Dockerfile 只能有一条 CMD 命令。如指定了多条,只有最后一条被执行
-
如果用户启动容器时用 docker run xxx 指定运行的命令,则会覆盖 CMD 指定的命令
#格式1:使用exec形式,推荐方式,第一个参数必须是命令的全路径,此种形式不支持环境变量,注意:是双引
号,不能是单引号
CMD ["executable","param1","param2"]
#格式2:shell形式,默认/bin/sh 中执行,提供给需要交互的应用;此种形式支持环境变量,相当于执行
/bin/sh -c "command param1 param2"
CMD command param1 param2
#指定不同的shell
#方法1
SHELL ["/bin/bash", "-c"]
CMD command param1 param2
#方法2
CMD ["/bin/bash", "-c","executable","param1","param2"]
#格式3:使用exec形式,提供给 ENTRYPOINT 命令的充当其参数
CMD ["param1","param2"]
范例:
CMD ["nginx", "-g", "daemon off;"]
CMD ["/apps/nginx/sbin/nginx", "-g","daemon off;"]
#如下格式报错
CMD /apps/nginx/sbin/nginx -g ”daemon off;"
范例:通过CMD基于alpine编译安装Nginx并结合脚本实现启动容器时的定制功能
[root@ubuntu2404 dockerfile]#cat Dockerfile
FROM busybox
LABEL maintainer="wangxiaochun <root@wangxiaochun.com>"
ENV ROOT /data/website
COPY index.html ${ROOT}/index.html
CMD /bin/httpd -f -h ${ROOT}
EXPOSE 80
EXPOSE:暴露端口
指定服务端的容器需要对外暴露(监听)的端口号,以实现容器与外部通信。
EXPOSE 仅仅是声明容器打算使用什么端口而已,并不会真正暴露端口,即不会自动在宿主进行端口映射,因此,在启动容器时需要通过 -P 或 -p ,Docker 主机才会真正分配一个端口转发到指定暴露的端口才可使用
注意:即使Dockerfile没有EXPOSE端口指令,也可以通过docker run -p临时暴露容器内程序真正监听的端口,所以EXPOSE 相当于指定默认的暴露端口,可以通过docker run -P 进行真正暴露
EXPOSE <port>[/ <protocol>] [<port>[/ <protocol>] ..]
范例
EXPOSE 80 443
EXPOSE 11211/udp 11211/tcp
[root@ubuntu2404 dockerfile]#vim Dockerfile
FROM busybox
LABEL maintainer="wangxiaochun <root@wangxiaochun.com>"
COPY index.html /data/website/
EXPOSE 80
Dockerfile构建过程和指令总结
dockerfile构建过程
-
从基础镜像运行一个容器
-
执行一条指令,对容器做出修改
-
执行类似docker commit的操作,提交一个新的中间镜像层(可以利用中间层镜像创建容器进行调试和排错)
-
再基于刚提交的镜像运行一个新容器
-
执行Dockerfile中的下一条指令,直至所有指令执行完毕
构建镜像docker build命令
docker build命令使用Dockerfile文件创建镜像
docker build [OPTIONS] PATH | URL | -
说明:
PATH | URL | - #可以使是本地路径,也可以是URL路径。若设置为 - ,则从标准输入获取
Dockerfile的内容
-f, --file string #Dockerfile文件名,默认为 PATH/Dockerfile
--force-rm #总是删除中间层容器,创建镜像失败时,删除临时容器
--no-cache #不使用之前构建中创建的缓存
-q --quiet=false #不显示Dockerfile的RUN运行的输出结果
--rm=true #创建镜像成功时,删除临时容器
-t --tag list #设置注册名称、镜像名称、标签。格式为 <注册名称>/<镜像名称>:<标签>(标签默认为latest)
构建命令
# 基础格式
docker build -t 镜像名:标签 .
# 示例(构建一个叫 myapp 的镜像,版本 latest)
docker build -t myapp:latest .
制定dockerfile路径(不在当前目录)
docker build -t myapp:v1.0 -f ./path/Dockerfile .
-f:指定具体的 Dockerfile 文件
范例:利用Dockerfile构建基于CentOS的nginx镜像
[root@ubuntu2404 ~]#docker build -t nginx_centos8.2:v1.14.1 /data/
容器数据持久保存方式(重点)
如果要将写入到容器的数据永久保存,则需要将容器中的数据保存到宿主机的指定目录
Docker 提供了多种方法将宿主机的文件系统挂载到容器内,包括以下几种主要方式:
-
绑定挂载,直接映射宿主机目录
-
卷(Volume)
这是 Docker 推荐的挂载方式
卷是完全由 Docker 管理的文件目录,可以在容器之间共享和重用。
在创建卷时,Docker 创建了一个目录在宿主机上,然后将这个目录挂载到容器内。卷的主要优点是你可以使用 Docker CLI 或 Docker API 来备份、迁移或者恢复卷,而无需关心卷在宿主机上的具体位置。
卷分为匿名卷和命名卷
数据卷(data volume)
数据卷的特点和使用
数据卷实际上就是宿主机上的目录或者是文件,可以被直接mount到容器当中使用 实际生成环境中,需要针对不同类型的服务、不同类型的数据存储要求做相应的规划,最终保证服务的可扩展性、稳定性以及数据的安全性
数据安全使用场景
-
数据库
-
日志输出
-
静态web页面
-
应用配置文件
-
多容器间目录或文件共享
数据卷的特点
-
数据卷是目录或者文件,并且可以在多个容器之间共同使用,实现容器之间共享和重用
-
对数据卷更改数据在所有容器里面会立即更新。
-
数据卷的数据可以持久保存,即使删除使用使用该容器卷的容器也不影响。
-
在容器里面的写入数据不会影响到镜像本身,即数据卷的变化不会影响镜像的更新
-
依赖于宿主机目录,宿主机出问题,上面容器会受影响,当宿主机较多时,不方便统一管理
-
匿名和命名数据卷在容器启动时初始化,如果容器使用的镜像在挂载点包含了数据,会拷贝到新初始化的数据卷中
数据卷分类
启动容器时,可以指定使用数据卷实现容器数据的持久化有三种
-
指定宿主机目录或文件: 指定宿主机的具体路径和容器路径的挂载关系,此方式不会创建数据卷
-
匿名卷: 不指定数据名称,只指定容器内目录路径充当挂载点,docker自动指定宿主机的路径进行挂载,此方式会创建匿名数据卷,Dockerfile中VOLUME指定的卷即为此种
-
命名卷: 指定数据卷的名称和容器路径的挂载关系,此方式会创建命名数据卷
数据卷的使用方法
docker run 命令的以下格式可以实现数据卷
-v, --volume=[host-src:]container-dest[:<options>]
<options>
ro 从容器内对此数据卷是只读,不写此项默认为可读可写
rw 从容器内对此数据卷可读可写,此为默认值
host-src 宿主机目录如果不存在,会自动创建
container-dest 容器目录如果不存在,会自动创建
命名卷
#命名卷将固定的存放在/var/lib/docker/volumes/<卷名>/_data
#注意:如果初始容器中有旧数据,将被复制到宿主机数据卷目录
-v <卷名>:<容器目录路径>
#可以通过以下命令事先创建,如可没有事先创建卷名,docker run时也会自动创建卷
docker volume create <卷名>
#示例:
docker volume create vol1 #也可以事先不创建
docker run -d -p 80:80 --name nginx01 -v vol1:/usr/share/nginx/html nginx
目录数据卷
在宿主机创建容器所使用的目录
[root@ubuntu2404 ~]#mkdir /data/testdir
[root@ubuntu2404 ~]#echo Test page on host > /data/testdir/index.html
查看容器相关目录路径
[root@ubuntu2404 ~]#docker images "*nginx*"
REPOSITORY TAG IMAGE ID CREATED
SIZE
nginx-ubuntu1804 1.16.1 19efdd23ac87 2 days ago
378MB
nginx-alpine 1.16.1 978a43bbb61d 2 days ago
211MB
[root@ubuntu2404 ~]#docker run -it --rm nginx-alpine:1.16.1 sh
/ # cat /apps/nginx/conf/nginx.conf
...
server {
location / {
root /data/nginx/html; #nginx存放网页文件的路径
index index.html index.htm;
}
...
/ # cat /data/nginx/html/index.html
Test Page based nginx-alpine
/ # exit
[root@ubuntu2404 ~]#docker ps -a
CONTAINER ID IMAGE COMMAND CREATED
STATUS PORTS NAMES
引用宿主机的数据卷启动容器
引用同一个数据卷目录,开启多个容器,实现多个容器共享数据
[root@ubuntu2404 ~]#docker run -d -v /data/testdir:/data/nginx/html/ -p
8001:80 nginx-alpine:1.16.1
56a5460f584bd2de56040c4a1dff86ad8a9723cfd6bf21ed8a538b9629b0874c
[root@ubuntu2404 ~]#docker run -d -v /data/testdir:/data/nginx/html/ -p
8002:80 nginx-alpine:1.16.1
e7b5bff6ce56fa51ed6411175c9c9f1fb9bf8e7b1b9471080380b01692f89e58
[root@ubuntu2404 ~]#docker ps
CONTAINER ID IMAGE COMMAND CREATED
STATUS PORTS NAMES
e7b5bff6ce56 nginx-alpine:1.16.1 "nginx" 6 seconds ago
Up 5 seconds 443/tcp, 0.0.0.0:8002->80/tcp hungry_robinson
56a5460f584b nginx-alpine:1.16.1 "nginx" 33 seconds ago
Up 31 seconds 443/tcp, 0.0.0.0:8001->80/tcp stupefied_dubinsky
[root@ubuntu2404 ~]#curl 127.0.0.1:8001
Test page on host
[root@ubuntu2404 ~]#curl 127.0.0.1:8002
Test page on host
进入到容器内测试写入数据
进入其中一个容器写入数据,可以其它容器的数据也变化
[root@ubuntu2404 ~]#docker exec -it e7b5bff6ce56 sh
/ # cat /data/nginx/html/index.html
Test page on host
/ # echo Test page v2 on host > /data/nginx/html/index.html
#进入另一个容器看到数据变化
[root@ubuntu2404 ~]#docker exec -it 56a5460f584b sh
/ # cat /data/nginx/html/index.html
Test page v2 on host
#访问应用
[root@ubuntu2404 ~]#curl 127.0.0.1:8001
Test page v2 on host
[root@ubuntu2404 ~]#curl 127.0.0.1:8002
Test page v2 on host
在宿主机修改数据
[root@ubuntu2404 ~]#echo Test page v3 on host > /data/testdir/index.html
[root@ubuntu2404 ~]#cat /data/testdir/index.html
Test page v3 on host
[root@ubuntu2404 ~]#curl 127.0.0.1:8001
Test page v3 on host
[root@ubuntu2404 ~]#curl 127.0.0.1:8002
Test page v3 on host
[root@ubuntu2404 ~]#docker exec -it e7b5bff6ce56 sh
/ # cat /data/nginx/html/index.html
Test page v3 on host
[root@ubuntu2404 ~]#docker exec -it 56a5460f584b sh
/ # cat /data/nginx/html/index.html
Test page v3 on host
Docker网络管理
Docker的默认的网络通信
Docker服务安装完成之后,默认在每个宿主机会生成一个名称为docker0的网卡其IP地址都是172.17.0.1/16
容器名称互联
新建容器时,docker会自动分配容器名称,容器ID和IP地址,导致容器名称,容器ID和IP都不固定,那么如何区分不同的容器,实现和确定目标容器的通信呢?解决方案是给容器起个固定的名称,容器之间通过固定名称实现确定目标的通信
Docker网络连接模式(重点)
网络模式介绍
Docker 的网络支持 5 种网络模式:
-
none
-
host
-
bridge
-
container
-
network-name
范例: 查看默认的网络模式有三个
[root@ubuntu2404 ~]#docker network ls
NETWORK ID NAME DRIVER SCOPE
fe08e6d23c4c bridge bridge local
cb64aa83626c host host local
10619d45dcd4 none null local
网络模式指定
默认新建的容器使用Bridge模式,创建容器时,docker run 命令使用以下选项指定网络模式
修改默认的Bridge模式网络配置
#修改桥接地址
[root@ubuntu2404 ~]#vim /lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
--bip=10.100.0.1/24
[root@ubuntu2404 ~]#systemctl daemon-reload
[root@ubuntu2404 ~]#systemctl restart docker
[root@ubuntu2404 ~]#ip a
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state
DOWN group default
link/ether 02:42:e0:ef:72:05 brd ff:ff:ff:ff:ff:ff
inet 10.100.0.1/24 brd 10.100.0.255 scope global docker0
valid_lft forever preferred_lft forever
inet6 fe80::42:e0ff:feef:7205/64 scope link
valid_lft forever preferred_lft forever
范例: 修改Bridge网络配置方法2
[root@ubuntu2404 ~]#vim /etc/docker/daemon.json
{
"hosts": ["tcp://0.0.0.0:2375", "fd://"],
"bip": "192.168.100.100/24", #分配docker0网卡的IP,24是容器IP的netmask
"fixed-cidr": "192.168.100.128/26", #分配容器IP范围,26不是容器IP的子网掩码,只表示地址
范围
"fixed-cidr-v6": "2001:db8::/64",
"mtu": 1500,
"default-gateway": "192.168.100.200", #网关必须和bip在同一个网段
"default-gateway-v6": "2001:db8:abcd::89",
"dns": [ "1.1.1.1", "8.8.8.8"]
}
[root@ubuntu2404 ~]#systemctl restart docker
[root@ubuntu2404 ~]#ip a show docker0
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP
group default
link/ether 02:42:23:be:97:75 brd ff:ff:ff:ff:ff:ff
inet 192.168.100.100/24 brd 192.168.100.255 scope global docker0
valid_lft forever preferred_lft forever
inet6 fe80::42:23ff:febe:9775/64 scope link
valid_lft forever preferred_lft forever
host模式
如果指定host模式启动的容器,那么新创建的容器不会创建自己的虚拟网卡,而是直接使用宿主机的网卡和IP地址,因此在容器里面查看到的IP信息就是宿主机的信息,访问容器的时候直接使用宿主机IP+容器端口即可,不过容器内除网络以外的其它资源,如: 文件系统、系统进程等仍然和宿主机保持隔离
None模式
在使用 none 模式后,Docker 容器不会进行任何网络配置,没有网卡、没有IP也没有路由,因此默认无法与外界通信,需要手动添加网卡配置IP等,所以极少使用
Container模式
使用此模式创建的容器需指定和一个已经存在的容器共享一个网络,而不是和宿主机共享网络,新创建的容器不会创建自己的网卡也不会配置自己的IP,而是和一个被指定的已经存在的容器共享IP和端口范围,因此这个容器的端口不能和被指定容器的端口冲突,除了网络之外的文件系统、进程信息等仍然保持相互隔离,两个容器的进程可以通过lo网卡进行通信。
Container 模式特点
-
使用参数 –-network container:名称或ID 指定
-
与宿主机网络空间隔离
-
空器间共享网络空间,直接使用对方的网络
-
第一个容器的网络可能是bridge,或none,或者host,而第二个容器模式依赖于第一个容器,它们共享网络
-
如果第一个容器停止,将导致无法创建第二个容器
-
第二个容器可以直接使用127.0.0.1访问第一个容器
-
适合频繁的容器间的网络通信
-
默认不支持端口映射,较少使用
范例: 通过容器模式实现 wordpress
#方法1
#为wordpress暴露端口
[root@ubuntu2404 ~]#docker run -d -p 80:80 --name wordpress -v
/data/wordpress:/var/www/html --restart=always registry.cnbeijing.aliyuncs.com/wangxiaochun/wordpress:php8.2-apache
[root@ubuntu2404 ~]#docker run --network container:wordpress -e
MYSQL_ROOT_PASSWORD=123456 -e MYSQL_DATABASE=wordpress -e MYSQL_USER=wordpress -e
MYSQL_PASSWORD=123456 --name mysql -d -v /data/mysql:/var/lib/mysql --
restart=always registry.cn-beijing.aliyuncs.com/wangxiaochun/mysql:8.0.29-oracle
#方法2
#MySQL提前为wordpress暴露端口
[root@ubuntu2404 ~]#docker run -d -p 80:80 -e MYSQL_ROOT_PASSWORD=123456 -e
MYSQL_DATABASE=wordpress -e MYSQL_USER=wordpress -e MYSQL_PASSWORD=123456 --name
mysql --restart=always registry.cnbeijing.aliyuncs.com/wangxiaochun/mysql:8.0.29-oracle
[root@ubuntu2404 ~]#docker run -d --network container:mysql --name wordpress -
-restart=always registry.cn-beijing.aliyuncs.com/wangxiaochun/wordpress:php8.2-
apache
#注意:数据库主机地址为127.0.0.1或wordpress容器的IP,不支持localhost
自定义网络模式
除了以上的网络模式,也可以自定义网络,使用自定义的网段地址,网关等信息可以使用自定义网络模式,实现不同集群应用的独立网络管理,而互不影响,而且在网一个网络内,可以直接利用容器名相互访问,非常便利
自定义网络实现
[root@ubuntu2404 ~]#docker network --help
Usage: docker network COMMAND
Manage networks
Commands:
connect Connect a container to a network
create Create a network
disconnect Disconnect a container from a network
inspect Display detailed information on one or more networks
ls List networks
prune Remove all unused networks
rm Remove one or more networks
创建自定义网络
docker network create -d <mode> --subnet <CIDR> --gateway <网关> <自定义网络名称>
#注意mode不支持host和none,默认是bridge模式
-d <mode> 可省略,默认为bridge,支持bridge,overlay,macvlan等driver模式
创建自定义的网络
[root@ubuntu2404 ~]#docker network create -d bridge --subnet 172.27.0.0/16 --
gateway 172.27.0.1 test-net
c90dee3b7937e007ed31a8d016a9e54c0174d0d26487b154db0aff04d9016d5b
[root@ubuntu2404 ~]#docker network ls
NETWORK ID NAME DRIVER SCOPE
cabde0b33c94 bridge bridge local
cb64aa83626c host host local
10619d45dcd4 none null local
c90dee3b7937 test-net bridge local
利用自定义的网络创建容器
[root@ubuntu2404 ~]#docker run -it --rm --network test-net alpine sh
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
15: eth0@if16: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
state UP
link/ether 02:42:ac:1b:00:02 brd ff:ff:ff:ff:ff:ff
inet 172.27.0.2/16 brd 172.27.255.255 scope global eth0
valid_lft forever preferred_lft forever
/ # / # route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 172.27.0.1 0.0.0.0 UG 0 0 0 eth0
172.27.0.0 0.0.0.0 255.255.0.0 U 0 0 0 eth0
/ # cat /etc/resolv.conf
search wang.com wang.org
nameserver 127.0.0.11
options ndots:0
/ # ping -c1 www.baidu.com
PING www.baidu.com (111.206.223.172): 56 data bytes
64 bytes from 111.206.223.172: seq=0 ttl=127 time=5.053 ms
Docker Compose容器单机编排
Docker Compose介绍
当在宿主机启动较多的容器时候,如果仍用手动执行docker run 启动每个容器不仅很麻烦而且因为有依赖关系等导致容易出错,而且无法不方便分类管理
可以使用 docker 单机多容器的编排工具 docker-compose 解决docker-compose 项目是Docker 官方的开源项目,负责实现对Docker 容器集群的快速编排,可以用它同时管理多个容器
github地址: https://github.com/docker/compose
官方地址: https://docs.docker.com/compose/
安装Docker Compose
离线安装,直接从github或国内镜像站下载安装对应版本
此方法安装版本可方便指定,推荐方法,但网络下载较慢
[root@ubuntu2404 ~]#curl -L
https://github.com/docker/compose/releases/download/1.25.3/docker-compose-`uname
-s`-`uname -m` -o /usr/local/bin/docker-compose
#从国内镜像站下载
[root@ubuntu2404 ~]#curl -L
https://get.daocloud.io/docker/compose/releases/download/1.25.3/dockercompose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose
[root@ubuntu2404 ~]#chmod +x /usr/local/bin/docker-compose
[root@ubuntu2404 ~]#ldd /usr/local/bin/docker-compose
通过 Compose plugin 形式安装(包安装后自带工具)
范例:在Ubuntu22.04 安装docker-compose插件
[root@ubuntu2404 ~]#curl -fsSL https://mirrors.aliyun.com/dockerce/linux/ubuntu/gpg | sudo apt-key add -
[root@ubuntu2404 ~]#add-apt-repository "deb [arch=amd64]
https://mirrors.aliyun.com/docker-ce/linux/ubuntu $(lsb_release -cs) stable"
[root@ubuntu2404 ~]#apt update
[root@ubuntu2404 ~]#apt-get install docker-compose-plugin
[root@ubuntu2404 ~]#docker version
docker-compose命令
进入项目目录(有 docker-compose.yml)
后台启动所有服务
docker-compose up -d
查看运行状态
docker-compose ps
日志
docker-compose logs -f
容器操作
docker-compose exec web bash
停止并清理
docker-compose down
删除容器
#docker-compose rm
小技巧:粘贴前,先在 vim 里按 :set paste,再按 i 进入插入模式粘贴,能避免自动缩进导致的格式混乱。
vim ~/.vimrc
" 按 F2 一键切换 paste 模式,底部会提示 [PASTE]
set pastetoggle=<F2>
" 粘贴时保留原格式的辅助配置
set expandtab
set tabstop=2
set shiftwidth=2
set autoindent
进入 vim 编辑文件,按 F2,底部会显示 -- INSERT (paste) --,此时粘贴内容不会乱缩进
粘贴完成后,再按 F2 退出 paste 模式,恢复正常编辑
从docker compose启动单个容器
创建docker compose文件
docker compose 文件可在任意目录,创建文件名为docker-compose.yml 配置文件,要注意前后的缩进
[root@ubuntu2404 ~]#docker-compose --version
docker-compose version 1.25.4, build unknown
[root@ubuntu2404 ~]#mkdir /data/docker-compose
[root@ubuntu2404 ~]#cd /data/docker-compose
[root@ubuntu2404 docker-compose]#vim docker-compose.yml
[root@ubuntu2404 docker-compose]#cat docker-compose.yml
service-nginx-web:
image: harbor.wang.org/example/nginx-centos7-base:1.6.1
container_name: nginx-web
expose:
- 80
- 443
ports:
- "80:80"
- "443:443"
查看配置和格式检查
只检查语法,不输出内容
[root@ubuntu2404 docker-compose]#docker-compose config -q
Docker仓库管理
Docker仓库,类似于yum仓库,是用来保存镜像的仓库。
为了方便的管理和使用docker镜像,可以将镜像集中保存至Docker仓库中,将制作好的镜像push到仓库集中保存,在需要镜像时,从仓库中pull镜像即可。
Docker之分布式仓库Harbor
企业级私有Registry服务器,Harbor 提供了更好的性能和安全。提升用户使用Registry构建和运行环境传输镜像的效率。Harbor支持安装在多个Registry节点的镜像资源复制,镜像全部保存在私有Registry 中, 确保数据和知识产权在公司内部网络中管控,另外,Harbor也提供了高级的安全特性,诸如用户管理,访问控制和活动审计等
vmware 官方开源服务: https://vmware.github.io/
harbor 官方github 地址: https://github.com/vmware/harbor
harbor 官方网址: https://goharbor.io/
harbor 官方文档: https://goharbor.io/docs/
github文档: https://github.com/goharbor/harbor/tree/master/docs
Harbor组成

安装Harbor
下载地址: https://github.com/vmware/harbor/releases
安装文档
https://goharbor.io/docs/2.12.0/install-config/
https://github.com/goharbor/harbor/blob/master/docs/install-config/_index.md
https://goharbor.io/docs/2.10.0/install-config/
安装Harbor前必须先安装Docker & Docker Compose才行
下载并解压 Harbor
cd /opt
sudo wget https://github.com/goharbor/harbor/releases/download/v2.15.0/harbor-offline-installer-v2.15.0.tgz
解压
sudo tar zxvf harbor-offline-installer-v2.15.0.tgz
cd harbor
配置 harbor.yml
复制模板
cp harbor.yml.tmpl harbor.yml
编辑harbor配置文件
# 改为你的服务器 IP 或域名
hostname: 10.0.0.134 # 改成你自己的IP
# HTTP 端口(默认80,冲突可改 8080)
http:
port: 80
# 注释掉 https 部分(测试环境)
# https:
# port: 443
# certificate: /your/cert.pem
# private_key: /your/key.pem
# 管理员初始密码(强烈建议修改)
harbor_admin_password: YourStrongPass123!
# 数据存储目录(默认 /data,确保空间足够)
data_volume: /data
安装 Harbor
sudo ./install.sh
验证 Harbor 容器
docker compose ps
设置 Harbor 开机自启(systemd)
创建 harbor.service
vim /etc/systemd/system/harbor.service
写入以下内容(路径必须与你实际一致):
[Unit]
Description=Harbor Image Registry
After=docker.service
Requires=docker.service
[Service]
Type=oneshot
RemainAfterExit=yes
WorkingDirectory=/opt/harbor
ExecStart=/usr/bin/docker compose up -d
ExecStop=/usr/bin/docker compose down
TimeoutStartSec=0
[Install]
WantedBy=multi-user.target
重载 systemd
sudo systemctl daemon-reload
启用开机自启 + 立即启动
systemctl enable --now harbor
检查状态
sudo systemctl status harbor
访问 Harbor

登录

使用私有仓库Harbor管理镜像
建立项目
harbor上必须先建立项目,才能上传镜像


创建用户和项目授权

在项目内对用户授权
注意:至少是开发者以上才能上传镜像

在所有docker客户端配置信任Harbor
#在每个docker客户端配置信任私有仓库
[root@ubuntu2404 ~]#vim /etc/docker/daemon.json
{
"insecure-registries": ["10.0.0.134:80","harbor.wang.org"] #说明: ":80"可省略
}
[root@ubuntu2404 ~]#systemctl restart docker
#添加域名解析
[root@ubuntu2404 ~]#echo 10.0.0.134 harbor.wang.org >> /etc/hosts
#确认域名解析
[root@ubuntu2404 ~]#tail -n 1 /etc/hosts
10.0.0.101 harbor.wang.org
#在每个docker客户端确认信任harbor
[root@ubuntu2404 ~]#docker info |grep -A 3 Insecure
Insecure Registries:
harbor.wang.org
::1/128
127.0.0.0/8
在docker客户端登录Harbor
#非交互登录
[root@ubuntu2404 ~]#docker login -u admin -p 123456 harbor.wang.org
WARNING! Using --password via the CLI is insecure. Use --password-stdin.
WARNING! Your credentials are stored unencrypted in '/root/.docker/config.json'.
Configure a credential helper to remove this warning. See
https://docs.docker.com/go/credential-store/
Login Succeeded
[root@ubuntu2404 ~]#cat .docker/config.json
{
"auths": {
"harbor.wang.org": {
"auth": "YWRtaW46MTIzNDU2"
}
}
}
给本地镜像打标签并上传到Harbor
#从阿里云上拉取镜像到本地
[root@ubuntu2404 ~]#docker pull registry.cn-beijing.aliyuncs.com/wangxiaochun/alpine:3.20.0
[root@ubuntu2404 ~]#docker tag registry.cn-beijing.aliyuncs.com/wangxiaochun/alpine:3.20.0 harbor.wang.org/example/alpine:3.20.0
[root@ubuntu2404 ~]#docker push harbor.wang.org/example/alpine:3.20.0
The push refers to repository [harbor.wang.org/example/alpine]
02f2bcb26af5: Pushed
3.20.0: digest:
sha256:216266c86fc4dcef5619930bd394245824c2af52fd21ba7c6fa0e618657d4c3b size:
528
访问harbor网站验证上传镜像成功

下载Harbor的镜像
#在另一台docker客户端确认信任harbor
[root@ubuntu2404 ~]#docker info |grep -A 3 Insecure
Insecure Registries:
harbor.wang.org
::1/128
127.0.0.0/8
#确认域名解析
[root@ubuntu2404 ~]#tail -n 1 /etc/hosts
10.0.0.134 harbor.wang.org
#在另一台docker客户端执行
[root@ubuntu2404 ~]#docker pull harbor.wang.org/example/alpine:3.20.0
3.20.0: Pulling from example/alpine
d25f557d7f31: Pull complete
Digest: sha256:216266c86fc4dcef5619930bd394245824c2af52fd21ba7c6fa0e618657d4c3b
Status: Downloaded newer image for harbor.wang.org/example/alpine:3.20.0
harbor.wang.org/example/alpine:3.20.0
[root@ubuntu2404 ~]#docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
harbor.wang.org/example/alpine 3.20.0 1d34ffeaf190 20 months ago 7.79MB
Docker的资源限制
容器资源限制介绍
官方文档
https://docs.docker.com/config/containers/resource_constraints/
默认情况下,容器没有资源的使用限制,可以使用主机内核调度程序允许的尽可能多的资源Docker 提供了控制容器使用资源的方法,可以限制容器使用多少内存或 CPU等, 在docker run 命令的运行时配置标志实现资源限制功能。
OOM
对于 Linux 主机,如果没有足够的内存来执行其他重要的系统任务,将会抛出OOM (Out of Memory Exception,内存溢出、内存泄漏、内存异常 ),随后系统会开始杀死进程以释放内存, 凡是运行在宿主机的进程都有可能被 kill ,包括 Dockerd和其它的应用程序, 如果重要的系统进程被 Kill,会导致和该进程相关的服务全部宕机。通常越消耗内存比较大的应用越容易被kill,比如: MySQL数据库,Java程序等
产生 OOM 异常时, Dockerd尝试通过调整 Docker 守护程序上的 OOM 优先级来减轻这些风险,以便它比系统上的其他进程更不可能被杀死但是每个容器 的 OOM 优先级并未调整, 这使得单个容器被杀死的可能性比 Docker守护程序或其他系统进程被杀死的可能性更大,不推荐通过在守护程序或容器上手动设置-- oom -score-adj为极端负数,或通过在容器上设置 – oom-kill-disable来绕过这些安全措施
容器的内存限制
Docker 可以强制执行硬性内存限制,即只允许容器使用给定的内存大小。
Docker 也可以执行非硬性内存限制,即容器可以使用尽可能多的内存,除非内核检测到主机上的内存不够用了
docker run 运行容器使用以下设置大部分的选项取正整数,跟着一个后缀 b , k , m , g ,,表示字节,千字节,兆字节或千兆字节
官文文档: https://docs.docker.com/config/containers/resource_constraints/
范例
[root@ubuntu2404 ~]#docker run -e MYSQL_ROOT_PASSWORD=123456 -it --rm -m 1g --oom-kill-disable mysql:5.7.30
#ubuntu2204和ubuntu2404内核不支持--oom-kill-disable
[root@ubuntu2404 ~]#docker run --rm --name test -m 256m --oom-kill-disable registry.cn-beijing.aliyuncs.com/wangxiaochun/stress-ng --vm 2
WARNING: Your kernel does not support OomKillDisable. OomKillDisable discarded.
[root@ubuntu2404 ~]#docker run --rm --name test -m 256m --oom-kill-disable
registry.cn-beijing.aliyuncs.com/wangxiaochun/stress-ng --vm 2
Status: Downloaded newer image for registry.cnbeijing.aliyuncs.com/wangxiaochun/stress-ng:latest
WARNING: Your kernel does not support OomKillDisable. OomKillDisable discarded.
范例
[root@ubuntu2404 ~]#sysctl -a |grep swappiness
sysctl: reading key "net.ipv6.conf.all.stable_secret"
sysctl: reading key "net.ipv6.conf.default.stable_secret"
sysctl: reading key "net.ipv6.conf.docker0.stable_secret"
sysctl: reading key "net.ipv6.conf.eth0.stable_secret"
sysctl: reading key "net.ipv6.conf.lo.stable_secret"
vm.swappiness = 60
容器的CPU限制
一个宿主机,有几十个核心的CPU,但是宿主机上可以同时运行成百上千个不同的进程用以处理不同的任务,多进程共用一个 CPU 的核心为可压缩资源,即一个核心的 CPU 可以通过调度而运行多个进程,但是同一个单位时间内只能有一个进程在 CPU 上运行,那么这么多的进程怎么在 CPU 上执行和调度的呢?
范例: 限制CPU
[root@ubuntu2404 ~]#docker run --rm --name c1 --cpu-quota 2000 --cpu-period
1000 registry.cn-beijing.aliyuncs.com/wangxiaochun/stress-ng --cpu 4
stress-ng: info: [1] defaulting to a 86400 second run per stressor
stress-ng: info: [1] dispatching hogs: 4 cpu, 4 vm
[root@ubuntu2404 ~]#docker stats --no-stream
CONTAINER ID NAME CPU % MEM USAGE /
LIMIT MEM % NET I/O BLOCK I/O PIDS
bd949bb6698e affectionate_chebyshev 185.03% 1.037GiB /
2.908GiB 35.64% 836B / 0B 0B / 0B 13
[root@ubuntu2404 ~]#
范例: 多个容器的CPU利用率比例
#同时开两个容器
[root@ubuntu2404 ~]#docker run -it --rm --name c1 --cpu-shares 1000
registry.cn-beijing.aliyuncs.com/wangxiaochun/stress-ng --cpu 4
stress-ng: info: [1] defaulting to a 86400 second run per stressor
stress-ng: info: [1] dispatching hogs: 4 cpu, 4 vm
[root@ubuntu2404 ~]#docker run -it --rm --name c2 --cpu-shares 500 registry.cnbeijing.aliyuncs.com/wangxiaochun/stress-ng --cpu 4
stress-ng: info: [1] defaulting to a 86400 second run per stressor
stress-ng: info: [1] dispatching hogs: 4 cpu, 4 vm
实战
基于Alpine基础镜像制作Nginx源码编译镜像
制作Alpine的自定义系统镜像
#按照业务类型或系统类型等方式划分创建目录环境,方便后期镜像比较多的时候进行分类
[root@ubuntu2404 ~]#mkdir
/data/dockerfile/{web/{nginx,apache,tomcat,jdk},system/{centos,ubuntu,alpine,deb
ian}} -p
[root@ubuntu2404 ~]#tree /data/dockerfile/
/data/dockerfile/
├── system
│ ├── alpine
│ ├── centos
│ ├── debian
│ └── ubuntu
└── web
├── apache
├── jdk
├── nginx
└── tomcat
#下载alpine镜像,打新标签
[root@ubuntu2404 ~]#docker pull alpine
[root@ubuntu2404 ~]#docker tag alpine alpine:3.11
[root@ubuntu2404 ~]#docker images
[root@ubuntu2404 ~]#docker images
REPOSITORY TAG IMAGE ID CREATED
SIZE
alpine 3.11 e7d92cdc71fe 11 days ago
5.59MB
alpine latest e7d92cdc71fe 11 days ago
5.59MB
#准备相关文件
[root@ubuntu2404 ~]#cd /data/dockerfile/system/alpine
[root@ubuntu2404 alpine]#cat repositories
http://mirrors.aliyun.com/alpine/v3.11/main
http://mirrors.aliyun.com/alpine/v3.11/community
#准备Dockerfile文件
[root@ubuntu2404 alpine]#cat Dockerfile
ARG VERSION=3.11
FROM alpine:$VERSION
LABEL maintainer="wangxiaochun <root@wangxiaochun.com>"
#COPY repositories /etc/apk/repositories
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/' /etc/apk/repositories
&& apk update && apk --no-cache add tzdata gcc make curl zip unzip net-tools
pstree wget libgcc libc-dev libcurl libc-utils pcre-dev zlib-dev libnfs pcre
pcre2 libevent libevent-dev iproute2 && ln -s /usr/share/zoneinfo/Asia/Shanghai
/etc/localtime && echo "Asia/Shanghai" > /etc/timezone
#准备构建脚本
[root@ubuntu2404 alpine]#cat build.sh
#!/bin/bash
docker build -t alpine-base:3.11 .
[root@ubuntu2404 alpine]#bash build.sh
[root@ubuntu2404 alpine]#docker images alp*
制作Alpine的自定义镜像的nginx镜像
#准备相关文件
[root@ubuntu2404 ~]#mkdir /data/dockerfile/web/nginx/1.16.1-alpine/
[root@ubuntu2404 ~]#cd /data/dockerfile/web/nginx/1.16.1-alpine/
[root@ubuntu2404 1.16.1-alpine]#wget http://nginx.org/download/nginx-
1.16.1.tar.gz
[root@ubuntu2404 1.16.1-alpine]#echo Test Page based nginx-alpine > index.html
[root@ubuntu2404 1.16.1-alpine]#cp ../1.16.1-centos7/nginx.conf .
[root@ubuntu2404 1.16.1-alpine]#cat nginx.conf
user nginx;
worker_processes 1;
daemon off; #必须为前台运行
...
location / {
root /data/nginx/html;
...
#编写Dockerfile文件
[root@ubuntu2404 1.16.1-alpine]#vim Dockerfile
[root@ubuntu2404 1.16.1-alpine]#cat Dockerfile
ARG VERSION=3.11
FROM alpine-base:$VERSION
ARG NGINX_VERSION=1.16.1
LABEL maintainer="wangxiaochun <root@wangxiaochun.com>"
ADD nginx-${NGINX_VERSION}.tar.gz /usr/local/src
ENV NGINX_DIR=/apps/nginx
RUN cd /usr/local/src/nginx-$NGINX_VERSION && ./configure --prefix=${NGINX_DIR}
&& make && make install && ln -s $NGINX_VERSION/sbin/nginx /usr/local/sbin/ &&
addgroup -g 888 -S nginx && adduser -s /sbin/nologin -S -D -u 888 -G nginx
nginx
COPY nginx.conf ${NGINX_DIR}/conf/nginx.conf
ADD index.html ${NGINX_DIR}/html/index.html
RUN chown -R nginx.nginx /data/nginx/ ${NGINX_DIR}/
EXPOSE 80 443
CMD ["nginx"]
#构建镜像
[root@ubuntu2404 1.16.1-alpine]#vim build.sh
[root@ubuntu2404 1.16.1-alpine]#cat build.sh
#!/bin/bash
#********************************************************************
docker build -t nginx-alpine:1.16.1 .
[root@ubuntu2404 1.16.1-alpine]#ls
build.sh Dockerfile index.html nginx-1.16.1.tar.gz nginx.conf
[root@ubuntu2404 1.16.1-alpine]#docker images “*alpine*”
REPOSITORY TAG IMAGE ID CREATED
SIZE
nginx-alpine 1.16.1 344ff9acf58b 13 seconds ago
211MB
alpine-base 3.11 b162eecf4da9 About an hour ago
182MB
alpine 3.11 e7d92cdc71fe 11 days ago
5.59MB
alpine latest e7d92cdc71fe 11 days ago
5.59MB
#生成容器测试镜像
[root@ubuntu2404 1.16.1-alpine]#docker run -d -p 80:80 nginx-alpine:1.16.1
1cb16e9fe6cd8e583a61c2718a92ce3031313bbf3656c2f85ac84d34ccfe7e0d
[root@ubuntu2404 1.16.1-alpine]#curl 127.0.0.1
Test Page based nginx-alpine
[root@ubuntu2404 1.16.1-alpine]#docker exec -it 1cb16e9fe6cd sh
/ # ps aux
PID USER TIME COMMAND
1 root 0:00 nginx: master process nginx
6 nginx 0:00 nginx: worker process
7 root 0:00 sh
12 root 0:00 ps aux
/ # ls /data/nginx/html/ -l
total 4
-rw-r--r-- 1 nginx nginx 29 Jan 29 11:08 index.html
/ # exit
[root@ubuntu2404 1.16.1-alpine]#
安战案例: MySQL使用的数据卷
[root@ubuntu2404 ~]#docker pull registry.cnbeijing.aliyuncs.com/wangxiaochun/mysql:8.0.29-oracle
[root@ubuntu2404 ~]#docker images "mysql*"
REPOSITORY TAG IMAGE ID CREATED
SIZE
mysql 8.0.29-oracle b598110d0fff 2 weeks ago
435MB
[root@ubuntu2404 ~]#docker run -d -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456
mysql:5.7.30
[root@ubuntu2404 ~]#docker ps
CONTAINER ID IMAGE COMMAND CREATED
STATUS PORTS NAMES
c21ca6f8a7fe 8.0.29-oracle "docker-entrypoint.s…" 3 minutes ago
Up 3 minutes 0.0.0.0:3306->3306/tcp, 33060/tcp nifty_banach
[root@ubuntu2404 ~]#docker exec -it c21ca6f8a7fe bash
root@c21ca6f8a7fe:/# cat /etc/issue
Debian GNU/Linux 9 \n \l
root@c21ca6f8a7fe:/# cat /etc/mysql/my.cnf
......
!includedir /etc/mysql/conf.d/
!includedir /etc/mysql/mysql.conf.d/
root@c21ca6f8a7fe:/# cat /etc/mysql/mysql.conf.d/mysqld.cnf
[mysqld]
pid-file = /var/run/mysqld/mysqld.pid
socket = /var/run/mysqld/mysqld.sock
datadir = /var/lib/mysql #数据存放路径
root@c21ca6f8a7fe:/# pstree -p
mysqld(1)-+-{mysqld}(130)
|-{mysqld}(131)
|-{mysqld}(132)
|-{mysqld}(133)
|-{mysqld}(134)
|-{mysqld}(135)
|-{mysqld}(136)
|-{mysqld}(137)
|-{mysqld}(138)
|-{mysqld}(139)
|-{mysqld}(140)
|-{mysqld}(141)
|-{mysqld}(143)
|-{mysqld}(144)
|-{mysqld}(145)
|-{mysqld}(146)
|-{mysqld}(147)
|-{mysqld}(148)
|-{mysqld}(149)
|-{mysqld}(150)
|-{mysqld}(151)
|-{mysqld}(152)
|-{mysqld}(153)
|-{mysqld}(154)
|-{mysqld}(155)
`-{mysqld}(156)
[root@ubuntu2404 ~]#mysql -uroot -p123456 -h127.0.0.1
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.7.30 MySQL Community Server (GPL)
Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
4 rows in set (0.00 sec)
mysql> create database dockerdb;
Query OK, 1 row affected (0.00 sec)
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| dockerdb |
| mysql |
| performance_schema |
| sys |
+--------------------+
5 rows in set (0.01 sec)
mysql>
#删除容器后,再创建新的容器,数据库信息丢失
[root@ubuntu2404 ~]#docker rm -f c21ca6f8a7fe
c21ca6f8a7fe
[root@ubuntu2404 ~]#docker run -d --name mysql -p 3306:3306 -e
MYSQL_ROOT_PASSWORD=123456 registry.cnbeijing.aliyuncs.com/wangxiaochun/mysql:8.0.29-oracle
f52a50c7f80ee39d9a935a762eacb05db72dcfa5f0d02af8b4f23b5538080b67
[root@ubuntu2404 ~]#mysql -uroot -p123456 -h127.0.0.1
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.7.30 MySQL Community Server (GPL)
Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
4 rows in set (0.00 sec)
#利用数据卷创建容器
[root@ubuntu2404 ~]#mkdir /data/mysql
[root@ubuntu2404 ~]#docker run -d --name mysql -p 3306:3306 -v
/data/mysql/:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 registry.cnbeijing.aliyuncs.com/wangxiaochun/mysql:8.0.29-oracle
d64ef3f9a64491061132020306fd3e97e1aa361b0fb9f6f644f2a1e3f334119c
[root@ubuntu2404 ~]#mysql -uroot -p123456 -h127.0.0.1
mysql> create database dockerdb;
Query OK, 1 row affected (0.00 sec)
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| dockerdb |
| mysql |
| performance_schema |
| sys |
+--------------------+
5 rows in set (0.00 sec)
mysql> exit
#删除容器,数据存放在挂载数据卷中,不会删除
[root@ubuntu2404 ~]#docker rm -fv mysql
mysql
[root@ubuntu2404 ~]#ls /data/mysql/
auto.cnf ca.pem client-key.pem ib_buffer_pool ib_logfile0 ibtmp1
performance_schema public_key.pem server-key.pem
ca-key.pem client-cert.pem dockerdb ibdata1 ib_logfile1 mysql
private_key.pem server-cert.pem sys
#重新创建新容器,之前数据还在
[root@ubuntu2404 ~]#docker run -d --name mysql -p 3306:3306 -v
/data/mysql/:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7.30
8d6cd0822cc61db30c0401992d2dbfa5c33b525f9aead44c165e0e247c37e5df
[root@ubuntu2404 ~]#mysql -uroot -p123456 -h127.0.0.1
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.7.30 MySQL Community Server (GPL)
Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| dockerdb |
| mysql |
| performance_schema |
| sys |
+--------------------+
5 rows in set (0.00 sec)
mysql> exit
#指定多个数据卷,创建MySQL
[root@ubuntu2404 ~]#docker run --name mysql-test1 -v /data/mysql:/var/lib/mysql
-e MYSQL_ROOT_PASSWORD=123456 -e MYSQL_DATABASE=wordpress -e MYSQL_USER=wpuser -e
MYSQL_PASSWORD=123456 -d -p 3306:3306 mysql:5.7.30
[root@ubuntu2404 ~]#docker run --name mysql-test2 -v
/root/mysql/:/etc/mysql/conf.d -v /data/mysql2:/var/lib/mysql --env-file=env.list
-d -p 3307:3306 mysql:5.7.30
[root@ubuntu2404 ~]#cat mysql/mysql-test.cnf
[mysqld]
server-id=100
log-bin=mysql-bin
[root@ubuntu2404 ~]#cat env.list
MYSQL_ROOT_PASSWORD=123456
MYSQL_DATABASE=wordpress
MYSQL_USER=wpuser
MYSQL_PASSWORD=wppass
文件数据卷
文件挂载用于很少更改文件内容的场景,比如: nginx 的配置文件、tomcat的配置文件等。
准备相关文件
[root@ubuntu2404 ~]#mkdir /data/{bin,testapp,logs}
[root@ubuntu2404 ~]#echo testapp v1 > /data/testapp/index.html
[root@ubuntu2404 ~]#cat /data/testapp/index.html
testapp v1
[root@ubuntu2404 ~]#cp /data/dockerfile/web/tomcat/tomcat-base-8.5.50/apachetomcat-8.5.50/bin/catalina.sh /data/bin/
[root@ubuntu2404 ~]#vim /data/bin/catalina.sh
#加下面tomcat的优化参数行
# -----------------------------------------------------------------------------
JAVA_OPTS="-server -Xms4g -Xmx4g -Xss512k -Xmn1g -
XX:CMSInitiatingOccupancyFraction=65 -XX:+UseFastAccessorMethods -
XX:+AggressiveOpts
-XX:+UseBiasedLocking -XX:+DisableExplicitGC -XX:MaxTenuringThreshold=10 -
XX:NewSize=2048M -XX:MaxNewSize=2048M -XX:NewRatio=2 -XX:Pe
rmSize=128m -XX:MaxPermSize=512m -XX:CMSFullGCsBeforeCompaction=5 -
XX:+ExplicitGCInvokesConcurrent -XX:+UseConcMarkSweepGC -XX:+UsePar
NewGC -XX:+CMSParallelRemarkEnabled -XX:+UseCMSCompactAtFullCollection -
XX:LargePageSizeInBytes=128m -XX:+UseFastAccessorMethods"
# OS specific support. $var _must_ be set to either true or false.
[root@ubuntu2404 ~]#chown 2019:2019 /data/bin/catalina.sh
[root@ubuntu2404 ~]#ll /data/bin/catalina.sh
-rwxr-x--- 1 2019 2019 24324 Jan 31 21:43 /data/bin/catalina.sh*
[root@ubuntu2404 ~]#chown 2019:2019 /data/logs/
引用文件数据卷启动容器
同时挂载可读可写方式的目录数据卷和只读方式的文件数据卷,实现三个数据卷的挂载,数据,日志和启动脚本
[root@ubuntu2404 ~]#docker run -d -v /data/bin/catalina.sh:/apps/tomcat/bin/catalina.sh:ro -v
/data/testapp:/data/tomcat/webapps/testapp -v /data/logs:/apps/tomcat/logs -p 8080:8080 tomcat-web:app1
55de76261c5e489de9a24d5533fe630d44aa7cce821627f6503a91c041c8f8d3
验证容器可以访问
[root@ubuntu2404 ~]#curl 127.0.0.1:8080/testapp/
testapp v1
[root@ubuntu2404 ~]#ls -l /data/logs/
total 36
drwxr-xr-x 2 2019 2019 4096 Jan 31 22:44 ./
drwxr-xr-x 7 root root 4096 Jan 31 22:43 ../
-rw-r----- 1 2019 2019 8336 Jan 31 22:44 catalina.2020-01-31.log
-rw-r----- 1 2019 2019 8808 Jan 31 22:44 catalina.out
-rw-r----- 1 2019 2019 0 Jan 31 22:44 host-manager.2020-01-31.log
-rw-r----- 1 2019 2019 0 Jan 31 22:44 localhost.2020-01-31.log
-rw-r----- 1 2019 2019 76 Jan 31 22:44 localhost_access_log.2020-01-31.txt
-rw-r----- 1 2019 2019 0 Jan 31 22:44 manager.2020-01-31.log
直接修改宿主机的数据
#宿主机修改目录数据卷
[root@ubuntu2404 ~]#echo testapp v2 > /data/testapp/index.html
[root@ubuntu2404 ~]#curl 127.0.0.1:8080/testapp/
testapp v2
[root@ubuntu2404 ~]#ll /data/bin/catalina.sh
-rwxr-x--- 1 2019 2019 24324 Jan 31 21:43 /data/bin/catalina.sh*
[root@ubuntu2404 ~]#echo >> /data/bin/catalina.sh
[root@ubuntu2404 ~]#ll /data/bin/catalina.sh
-rwxr-x--- 1 2019 2019 24325 Jan 31 22:21 /data/bin/catalina.sh*
进入容器修改数据
[root@ubuntu2404 ~]#docker exec -it 55de76261c5e bash
[root@55de76261c5e /]# netstat -ntl
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 127.0.0.1:8005 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:8009 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:8080 0.0.0.0:* LISTEN
#文件数据卷上的文件为只读
[root@55de76261c5e /]# echo >> /apps/tomcat/bin/catalina.sh
bash: /apps/tomcat/bin/catalina.sh: Read-only file system
#目录数据卷可读可写
[root@55de76261c5e /]# cat /data/tomcat/webapps/testapp/index.html
testapp v2
[root@55de76261c5e /]# echo testapp v3 > /data/tomcat/webapps/testapp/index.html
[root@55de76261c5e /]# cat /data/tomcat/webapps/testapp/index.html
testapp v3
[root@ubuntu2404 ~]#curl 127.0.0.1:8080/testapp/
testapp v3
实战案例:实现wordpress持久化(练习)
[root@ubuntu2404 ~]#docker run -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 -e
MYSQL_DATABASE=wordpress -e MYSQL_USER=wordpress -e MYSQL_PASSWORD=123456 --name
mysql -d -v /data/mysql:/var/lib/mysql --restart=always registry.cnbeijing.aliyuncs.com/wangxiaochun/mysql:8.0.29-oracle
[root@ubuntu2404 ~]#docker run -d -p 80:80 --name wordpress -v
/data/wordpress:/var/www/html --restart=always registry.cnbeijing.aliyuncs.com/wangxiaochun/wordpress:php8.2-apache
#注意:数据库服务器的地址要输入宿主机的IP,不能是127.0.0.1或localhost
实战案例:利用自定义网络实现Wordpress
docker network create -d bridge --subnet 172.37.0.0/16 --gateway 172.37.0.100 wordpress-net
docker run -d -p 80:80 --network wordpress-net --name wordpress --restart=always registry.cn-beijing.aliyuncs.com/wangxiaochun/wordpress:php8.2-apache
docker run --network wordpress-net -e MYSQL_ROOT_PASSWORD=123456 -e MYSQL_DATABASE=wordpress -e MYSQL_USER=wordpress -e MYSQL_PASSWORD=123456 --name mysql -d --restart=always registry.cn-beijing.aliyuncs.com/wangxiaochun/mysql:8.0.29-oracle



基于 Docker 运行 WordPress+MySQL
docker run -d --name mysql -e MYSQL_ROOT_PASSWORD=123456 -e MYSQL_DATABASE=wordpress -e MYSQL_USER=wordpress -e MYSQL_PASSWORD=654321 --restart always mysql:8.0.29-oracle
docker inspect -f '{{.NetworkSettings.Networks.bridge.IPAddress}}' mysql
docker run --name wordpress -p 80:80 -d \
-e WORDPRESS_DB_HOST=172.17.0.2 \
-e WORDPRESS_DB_USER=wordpress \
-e WORDPRESS_DB_PASSWORD=654321 \
-e WORDPRESS_DB_NAME=wordpress \
registry.cn-beijing.aliyuncs.com/wangxiaochun/wordpress:6.9.0-php8.5-apache
http://10.0.0.134/wp-admin/install.php

基于 Docker-compose 启动 WordPress
yml文件
services:
mysql:
container_name: mysql
networks:
- wordpress-net
environment:
- MYSQL_ROOT_PASSWORD=123456
- MYSQL_DATABASE=wordpress
- MYSQL_USER=wordpress
- MYSQL_PASSWORD=654321
volumes:
- /data/mysql:/var/lib/mysql
restart: always
image: mysql:8.0
wordpress:
ports:
- "80:80"
container_name: wordpress
networks:
- wordpress-net
environment:
- WORDPRESS_DB_HOST=mysql
- WORDPRESS_DB_NAME=wordpress
- WORDPRESS_DB_USER=wordpress
- WORDPRESS_DB_PASSWORD=654321
volumes:
- /data/wordpress:/var/www/html
image: wordpress:latest
depends_on:
- mysql
networks:
wordpress-net:
ipam:
driver: default
config:
- subnet: 172.27.0.0/16




AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)