Docker
技术文档:Get started | Docker Docs
概述
作用
- 跨平台快速构建应用:通过打包为镜像,解决每次部署都需安装依赖、进行环境配置,以及不同设备上部署产生的各种问题。通过镜像中心可以快速获取镜像。
- 各应用间隔离:Docker中不同容器间是相互隔离的,如一个容器内的应用发生内存泄漏,其最多影响到该容器,而不会导致整个系统的崩溃。且因为是相互隔离的,所以可以同时部署不同版本的相同应用,而不会出现冲突问题。

概念
仓库
仓库就是存放镜像的地方,仓库分为公有仓库和私有仓库。Docker 公司提供了公共的镜像仓库 https://hub.docker.com
镜像
Docker 将应用程序及其运行环境、依赖项打包成镜像,镜像包含了应用程序所需的所有内容,包括代码、运行时环境、系统工具、库和依赖项。相当于面向对象中的类,而容器则是镜像的实例对象,一个镜像可以实例化出多个容器。
容器
容器是镜像的运行时实例,可以被理解为一个隔离的、独立的运行时环境,其中包含了应用程序及其运行所需的一切。
- 虚拟机技术: 使用Hypervisor在物理服务器上创建多个完整的虚拟机。每个虚拟机都包含了自己的操作系统、内核和用户空间,相互独立。
- Docker容器:与宿主机共享同一个操作系统内核,但各自拥有自己的用户空间,这使得容器更为轻量级。

安装
# 移除旧版本docker
sudo yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
# 配置docker yum源。
sudo yum install -y yum-utils
sudo yum-config-manager \
--add-repo \
http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# 安装 最新 docker
sudo yum install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
# 启动& 开机启动docker; enable + start 二合一
systemctl enable docker --now
# 配置加速,如果registry-mirrors中镜像源无效,百度查找替换新的镜像源
# 如果镜像在下方的镜像源都找不到,最终还是会访问dockerhub官网的
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": [
"https://docker.1ms.run",
"https://registry.docker-cn.com",
"https://dockerhub.azk8s.cn",
"https://docker.1panelproxy.com/"
]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker使用
镜像命令
docker search(搜索镜像)

| 命令 | 作用 |
|---|---|
| docker search 镜像名称 | 搜索镜像 |
| docker search --limit 10 镜像名称 | 搜索镜像,同时显示显示的结果,只显示10条,不加参数,默认显示25条 |
docker pull(拉取镜像)
指定镜像版本拉取时,使用Docker Hub搜索,找到对应镜像,点击tags查看其所有版本
| 命令 | 作用 |
|---|---|
| docker pull 镜像名称 | 拉取latest版本的镜像 |
| docker pull 镜像名称:版本tag | 拉取指定版本的镜像 |
docker images(查看现有镜像)
| 命令 | 作用 |
|---|---|
| docker images | 查看本地所有镜像 |
| docker images -a | 查看本地所有镜像,包括中间层(intermediate layers)。 |
| docker images -q | 只显示镜像的ID |
| docker images -aq | 只显示镜像的ID,且显示中间层 |
docker rmi(删除镜像)
要删除镜像,需要先删除用这个镜像创建的容器(删除容器后面再讲),或者使用强制删除。
| 命令 | 作用 |
|---|---|
| docker rmi 镜像ID | 删除镜像,不需要输入完整id,只需要输入前几位且与其他镜像不重复即可 |
| docker rmi -f 镜像ID | 强制删除 |
| docker rmi 镜像名称 | 只会删除最新版本的镜像 |
| docker rmi 镜像名称:版本tag | 删除指定版本的镜像 |
| docker rmi 镜像ID1 镜像ID2 | 删除多个 |
| docker rmi -f $(docker images -qa) | 删除所有镜像,慎用或不用,docker images -qa是获取到镜像的ID |
docker system df(查看镜像、容器占用)

镜像推送
| 命令 | 作用 |
|---|---|
| docker login | 登录 docker hub |
| docker tag mynginx:v1.0 leifengyang/mynginx:v1.0 | 重新给镜像打标签 |
| docker push leifengyang/mynginx:v1.0 | 推送镜像 |
容器命令
docker run(启动容器)
docker run -d --name nginx nginx:latest:基于指定镜像nginx:latest创建一个容器(可以多次运行创建多个)
- 交互式容器:需要在前台运行以便与用户进行交互,如Ubuntu 容器、CentOS 容器,使用-it。
- 守护式容器:适合在后台运行,例如 redis,使用-d。
| 命令 | 作用 |
|---|---|
| docker run -d --name name 镜像 | -d表示后台启动,--name用于指定运行容器的名称 |
| docker run -it --name name 镜像 /bin/bash | -i 代表交互模式,使容器保持打开状态并等待用户命令输入;-t 分配一个伪终端或终端,使输入可见。 |
| docker run -d -p 6379:6379 <br>-e REDIS_REPLICATION_MODE=master <br/>-e REDIS_PASSWORD=12345<br/>redis | -e:用于设置启动应用的环境变量,通过参考DockerHub上镜像对应的说明来选择性配置。 |
资源占用限制
下方仅列出基本限制条件,这些限制条件可以组合使用
| 命令 | 作用 |
|---|---|
| docker run --cpus 2 image | 启动时指定容器占用CPU核心数,可以为小数 |
| docker update --cpus=2 container | 启动后修改容器占用CPU核心数,可以为小数 |
| docker run -m 512m image | 限制容器只能使用512MB的内存(单位m也可以替换为g) |
| docker run --memory-swap=1g image | 设置交换空间限制 |
docker exec/attach(进入容器)
| 命令 | 作用 |
|---|---|
| docker exec -it 容器ID或名称 /bin/bash | 在容器中打开新的终端,时候用 exit 退出容器,不会导致容器停止 |
| docker attach 容器ID或名称 | 不会启动新的进程,所以用 exit 退出,会终止当前容器运行 |
docker ps(查看容器)
| 命令 | 作用 |
|---|---|
| docker ps | 查看运行中的容器 |
| docker ps -a | 查看所有的容器,包括停止的 |
| docker ps -l | 查看最近创建的容器 |
| docker ps -q | 查看容器,只显示容器编号 |
| docker ps -n m | 查看最近m个创建的容器 |
docker stop/kill(停止容器)
| 命令 | 作用 |
|---|---|
| docker stop 容器ID/名称 | 停止前会向容器发送信号,做好数据保存准备 |
| docker kill 容器ID/名称 | 直接杀死。 |
docker start(运行已停止的容器)
| 命令 | 作用 |
|---|---|
| docker start 容器ID/名称 | 重新运行已停止的容器 |
docker restart(重启正在运行的容器)
| 命令 | 作用 |
|---|---|
| docker restart 容器ID/名称 | 重启正在运行的容器 |
docker rm(删除容器)
| 命令 | 作用 |
|---|---|
| docker rm 容器ID/名称 | 删除已停止的容器 |
| docker rm -f 容器ID/名称 | 强制删除容器,运行中的也可以删除 |
| docker rm -f $(docker ps -a -q) | 删除全部容器 |
| docker ps -a -q | xargs docker rm | 删除全部容器 |
端口映射
| 命令 | 作用 |
|---|---|
| docker run -p 6379:6379 镜像 | -p 表示端口映射,前面的 6379 表示宿主机的端口号,后面的 6379 表示容器的端口号。 |
| docker run -p 80:80 -p 8080:8080 镜像 | 指定多个端口映射 |
重启策略
no:默认策略,在容器退出时不进行重启。always:无论容器退出状态如何,都会尝试重启容器。on-failure:只有在容器以非零状态码退出时才尝试重启容器。unless-stopped:在容器退出或守护进程重启时,始终重启容器,除非用户明确停止了容器。
| 命令 | 作用 |
|---|---|
| docker run -d -p 6379:6379 --restart=always redis | 容器未启动,指定容器的重启策略 |
| docker update --restart=always <container_id> | 容器已经启动了,可以使用 update 命令修改容器的重启策略 |
docker logs(查看容器日志)
| 命令 | 作用 |
|---|---|
| docker logs 容器ID/名称 | 查看容器日志 |
docker inspect(查看容器详细信息)
| 命令 | 作用 |
|---|---|
| docker inspect 容器ID/名称 | 查看容器详细信息 |
docker cp(文件拷贝)
| 命令 | 作用 |
|---|---|
| docker cp 宿主机路径 容器ID:容器内路径 | 将宿主机的文件拷贝到容器 |
| docker cp 容器ID:容器内路径 宿主机路径 | 将容器的文件拷贝到宿主机 |
保存镜像
- export:把之前镜像的层级删干净,只保留最新的快照文件,只有一层。
- commit+save:保留了一个镜像的所有历史文件和元数据,它把容器的内容作为一个新的层覆盖在原有镜像之上,然后实现持久化。原有的镜像没有改变。
docker load/save(镜像导入/导出)
- docker save -o /opt/ nginx:latest
- docker load -i /opt/naginx-image
| 命令 | 作用 |
|---|---|
| docker save -o /path/name image_name:tag | 对当前的镜像进行持久化,形成tar文件 |
| docker load -i /path/name | 将tar文件加载为镜像 |
docker export/import(容器导入/导出)
| 命令 | 作用 |
|---|---|
| docker export 容器ID/名称 > 文件.tar | 对当前的容器状态建立快照,并持久化为tar文件 |
| docker import 文件.tar 镜像名称:版本标签 | 从tar包导入为镜像 |
docker commmit(导入/导出为镜像)
| 命令 | 作用 |
|---|---|
| docker commit -m="提交的描述信息" -a="作者" 容器ID 镜像名:[版本标签] | 把当前容器的内容新建一个层文件,覆盖在旧的镜像文件层之上,然后导出为新镜像 |
容器数据卷
当容器被删除后,内部运行的应用数据就会被删除。而将容器的目录与宿主机的目录进行映射,即使容器被删除,挂载到容器卷中的数据仍然会被保留在宿主机上。
目录挂载
如果宿主机或者容器内没有指定的目录(挂载的路径必须是绝对路径),则会自动创建(挂载的必须是目录)。
容器的目录变成了指向了宿主机的目录的一个链接,软件运行时使用的是宿主机目录下的内容,所以即使容器内目录有内容,也会丢失。
所以如果宿主机的挂载目录下没有文件,则容器被挂载目录下有文件也不起作用,如:将nginx的配置文件目录直接挂载到宿主机的空目录下,由于不存在内容,将会无法启动。
| 命令 | 作用 |
|---|---|
| docker run -d --privileged=true -v 宿主机目录:容器内目录 镜像 | --privileged=true:这个选项会赋予容器内的 root 用户几乎所有在宿主机上的 root 用户的权限。<br>-v :指定容器内目录挂载到宿主机的位置 |
卷映射
- 如果容器卷是空的而容器中的目录有内容,那么docker会将容器目录中的内容拷贝到容器卷中
- 如果容器卷中已经有内容,则会将容器中的目录覆盖。
- 容器卷由自己命名,存放在路径/var/lib/docker/volumes/下
| 命令 | 作用 |
|---|---|
| docker run --privileged=true -v 容器卷名:容器中目录 镜像 | --privileged=true:这个选项会赋予容器内的 root 用户几乎所有在宿主机上的 root 用户的权限。<br>-v :指定要挂载的容器目录 |
| docker volume ls | 查看 docker 中存在的卷 |
| docker inspect 卷名 | 命令查看容器卷的信息,可以找到其位置 |
| docker volume create 卷名称 | 创建容器卷,启动时可以直接使用,多个容器可以使用同一个卷 |
###############添加这3行
proxy_buffer_size 64k;
proxy_buffers 32 32k;
proxy_busy_buffers_size 128k;
###############添加这3行
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;docker网络
常用命令
| 命令 | 作用 |
|---|---|
| docker network ls | 查看所有网络模式 |
| docker network create 网络名称 | 创建指定网络 |
| docker network rm 网络ID/名称 | 删除指定网络 |
| docker network inspect 网络ID/名称 | 查看指定网络详细信息 |
三种模式
docker run -it --network none --name ubuntu-1 ubuntu /bin/bash:通过--network指定
- bridge网络模式:为每一个容器分配、设置 IP 等,并将容器连接到一个
docker0虚拟网桥,Docker 网络默认使用的就是该模式。注意,分配给容器的ip不是固定的。 - host网络模式:容器将不会虚拟出自己的网卡,而是使用宿主机的 IP 和端口,不需要映射端口,直接使用http://宿主机IP:端口号即可访问。
- none网络模式:不对容器进行任何网络设置,即无法使用网络,如果需要,只能自己添加网络配置。
自定义网络模式
1、通过docker network create 网络名创建,新创建的网络模式也是桥接模式(因为默认桥接网络不提供内置的服务发现机制,而自定义的提供,所以其才可以通过服务名来访问)
2、创建容器时指定新建网络的名称vv
# 创建ubuntu-1容器,并加入到doubi-network网络
docker run -it --network doubi-network --name ubuntu-1 ubuntu /bin/bash
# 创建ubuntu-2容器,并加入到doubi-network网络
docker run -it --network doubi-network --name ubuntu-2 ubuntu /bin/bash3、直接在容器1中执行ping ubuntu-2,可以ping通容器2
Dockerfile(构建镜像)
流程
1、编写一个 Dockerfile 文件(Dockerhub上可以直接查看对应应用的Dokcerfile文件)
# 例:构建SpringBoot的Dockerfile
FROM openjdk:17
LABEL author=leifengyang
COPY app.jar /app.jar
EXPOSE 8080
ENTRYPOINT ["java","-jar","/app.jar"]2、使用 docker build 命令运行脚本文件,构建成为一个镜像;
# -t指定镜像名称和版本,.表示在当前目录寻找Dockerfile文件
docker build -t myubuntu:1.0.0 .常用命令
FROM
指明构建的新镜像是基于哪个基础镜像
FROM <image>:<tag>LABEL
用于向镜像添加键值对,提供关于镜像的描述信息。
LABEL <key>=<value> <key>=<value> <key>=<value> ...RUN
在构建镜像时执行命令。RUN命令会在执行docker build命令的时候执行。每⼀条 RUN 指令都会在镜像上构建⼀层,可以将多个 RUN 命令合并为一条命令(会降低可读性),从而减少镜像的层数。
# 使用shell格式的run命令
RUN apt update && apt install -y vim
# 使用exec格式的run命令
RUN ["apt", "update", "&&", "apt", "install", "-y", "vim"]COPY
拷贝文件或目录到镜像中。
ADD
src 可以是一个本地文件或者是一个本地压缩文件,压缩文件会自动解压拷贝到镜像。还可以是一个 url,效果类似于 wget 命令,然后自动下载和解压。
ADD <src> <dest>
ADD https://example.com/file.tar.gz /tmp/WORKDIR
用于设置工作目录,此后的 RUN、CMD、ENTRYPOINT、COPY 、AND 等命令将在这个工作目录下执行。
WORKDIR 路径ENV
用于在构建镜像过程中设置环境变量
# 格式1
ENV key value
# 格式2
ENV key1=value1 key2=value2
# 设置一个名为 "WORK_HOME" 的环境变量
ENV WORK_HOME /home/doubi
# 通过$引用
WORKDIR $WORK_HOME
# 容器启动时可以通过-e覆盖环境变量
docker run -d -e SPRING_PROFILES_ACTIVE=dev -p 8080:8080 my_imageARG
与 ENV 命令作用一样,和 ENV 命令不同的是:这些变量只在构建过程中有效,构建完成后不会被保留在最终的镜像中。
# 定义构建参数
ARG VERSION=latest
ARG BUILD_DATE
# 使用构建参数设置环境变量
ENV APP_VERSION=$VERSION
ENV BUILD_DATE=$BUILD_DATE EXPOSE
表明容器在运行时会监听指定的网络端口,让使用者知道应用程序会使用哪些端口,实际上还需要run时指定端口映射。
# 暴露80端口
EXPOSE 80
# 暴露多个端口
EXPOSE 80 443
# 指定端口和协议
EXPOSE 8080/tcpCMD
为容器指定默认的执行命令或应用程序,当容器启动时,这个命令将被执行。如果在 Dockerfile 中存在多个 CMD命令,只有最后一个会生效
# 同样支持shell和exec两种格式
# Shell格式
CMD <command>
# Exec格式
CMD ["参数1", "参数2", ...]
# /bin/bash会替换掉 Tomcat Dockerfile文件中的 CMD
docker run -it -p 8080 tomcat /bin/bashVOLUME
VOLUME 命令用来做匿名挂载,在启动容器时忘记挂载数据卷,会自动挂载到匿名卷(/var/lib/docker/volumes/xxxx/_data下)
# 方式1
VOLUME <路径>
# 方式2
VOLUME <路径1> <路径2>
# 方式3
VOLUME ["<路径1>", "<路径2>"...]=Docker Compose
| 命令 | 作用 |
|---|---|
| docker compose config -q | 查看编写的compose文件是否存在问题,存在问题才会输出内容 |
| docker compose up -d | 后台启动所有容器 |
| docker compose down | 该命令不仅停止容器,还会直接删除容器、网络、容器卷,镜像不会删除,下次启动会重新启动。 |
| docker compose stop | 停止服务 |
| docker compose stop 容器服务名 | 停止docker-compose文件中定义的某一个容器服务 (yaml中定义的容器服务名称) |
| docker compose start | 启动已停止的容器 |
| docker compose start 容器服务名 | 启动docker-compose文件中定义的某一个容器服务(yaml中定义的容器服务名称) |
| docker compose restart | 重启 |
| docker compose restart 容器服务名 | 重启docker-compose文件中定义的某一个容器服务(yaml中定义的容器服务名称) |
| docker compose ps | 显示docker compose 编排的所有正在运行的容器 |
| docker compose ps -a | 容器服务名指的是docker-compose.yaml中定义的容器服务名称 |
name: myblog
services:
mysql:
container_name: mysql
image: mysql:8.0
ports:
- "3306:3306"
environment:
- MYSQL_ROOT_PASSWORD=123456
- MYSQL_DATABASE=wordpress
volumes:
# 卷映射,需要在下方声明mysql-data
- mysql-data:/var/lib/mysql
# 目录挂载
- /app/myconf:/etc/mysql/conf.d
restart: always
# 加入网络,可以加入一个,也可以加入多个
networks:
- blog
wordpress:
image: wordpress
ports:
- "8080:80"
environment:
#因为加入到了同一个网络,直接使用容器名就可以访问了
WORDPRESS_DB_HOST: mysql
WORDPRESS_DB_USER: root
WORDPRESS_DB_PASSWORD: 123456
WORDPRESS_DB_NAME: wordpress
volumes:
- wordpress:/var/www/html
restart: always
networks:
- blog
# 依赖于哪个服务,需要在这些服务后启动
depends_on:
- mysql
#服务名称:compose-boot,名称是自己定义的
compose-boot:
# 使用当前目录下的 Dockerfile 构建镜像,如果编排的镜像需要使用多个Dockerfile,那就需要将多个Dockerfile放到不同的目录了后指定路径
build: .
volumes:
- /home/doubi/compose-boot/logs:/logs
ports:
- 8080:8080
restart: always
networks:
- blog
depends_on:
- mysql
volumes:
mysql-data:
wordpress:
# 声明网络
networks:
blog: