docker 常用命令
docker 常用命令
资料
docker 服务操作
sudo systemctl start docker
sudo systemctl stop docker #停止
sudo systemctl restart docker #重新启动
sudo systemctl enable docker #开机自动启动
设置镜像加速
⚠️:此处以阿里云举例「加速地址只能在自己的云平台中使用」
阿里云 aliyun.com
登录 阿里云
选择菜单->【产品】-> 【容器】-> 【容器镜像服务 ACR】-> 点击按钮【管理控制台】-> 左侧菜单【镜像工具->镜像加速器】-> 会看到一个镜像加速地址
不收费
具体配置方法下面有详细的说明
#如果没有/etc/docker目录就建立,没有daemon.json文件就建立。 #此处举例为没有这个目录和文件 sudo mkdir -p /etc/docker sudo tee /etc/docker/daemon.json <<-'EOF' { "registry-mirrors": ["https://iiesyla9.mirror.aliyuncs.com"] } EOF sudo systemctl daemon-reload sudo systemctl restart docker
查看版本
docker --version 「-v」 只能查看版本号,不能看出来是ce 还是 io 版本。
docker version 可以查看时ce还是io版本。
配置文件位置
⚠️:没有 /etc/docker 目录和daemon.json 文件也是正常的。
linux
/etc/docker/daemon.json
mac
~/.docker/config.json
根目录存储位置
linux
docker info #命令,里面有一项 Docker Root Dir: /var/lib/docker #映像文件存储位置默认路径: /var/lib/dockermac
在docker的图形设置界面中,有一个磁盘的选项里面有具体大小的配置,是一个很大的raw文件。
查看容器详细信息
命令: docker inspect 容器名
Mounts:挂载的卷
Networks:网络信息
Ports:映射的端口
Config:包括:环境变量、Cmd、使用的映像、EntryPoint「入口命令」、Volumes等
监控docker
#类似linux的top命令
docker stats镜像操作
docker pull 镜像名称 「拉取镜像」
docker images 「查看本地镜像列表」
docker rmi 镜像名字 「删除指定镜像」
docker push 「推镜像到镜像仓库」
容器相关操作
docker create 「创建容器」
#使用docker镜像nginx:latest创建一个容器,并将容器命名为myrunoob docker create --name myrunoob nginx:latestdocker run 「创建并运行一个容器」
-d : 容器后台运行;不加这个参数会卡住在控制台,停止后进程会停止
--name 指定容器的名称
-p 宿主机端口:容器内端口
例如: -p 3307:3306
-e 环境变量,不同镜像的变量不同
mysql 是镜像的名字
完整写法: mysql:5.7
tag不写就是 lastest
-v 宿主机目录:容器内部目录
宿主机目录没有:自动创建
容器内部目录没有:自动创建
都没有:同时创建
-w
指定容器内部的工作目录
docker stop 容器 「停止容器的运行,并没有删除容器」
docker start 容器 「启动 容器进程」
docker ps
查看容器状态,默认只显示运行的容器 -a 查看所有容器
已表格的方式查看
docker rm
删除容器 容器中的数据会被删除
-f 强制删除容器,可以删除运行的容器
docker exec
执行命令进入容器内步
-it 进入交互状态
docker save 「可以写多个image,这样就把多个镜像保存了」
docker save -o 输出文件名.tar ngnix:latestdocker load 「不用写映像的名字,文件中自己会指定」
docker load -i file.tar docker logs 「查看容器日志」
#查看日志 -f 是follow的缩写,查看日志不停,持续输出
docker logs -f 容器名docker cp 「拷贝容器里面的文件到宿主机 nginx 是容器名称」
docker cp nginx:/etc/nginx/nginx.conf /home/nginx/conf/nginx.conf帮助
docker 命令 --help
#查看save命令的帮助
dockder save --help
#查看run命令的帮助
docker run --help磁盘的使用情况
docker system df
清理镜像、容器、卷、网络
清理 「镜像、容器、卷、网络的清理」
sudo docker image prune
清理悬空镜像
sudo docker system prune -a
清理未使用的镜像、容器、网络和卷
加上
-a参数后,命令还会删除所有未被容器使用的悬空镜像(dangling 和非 dangling 镜像都会被清理)。
#清理停止的容器
docker container prune
#清理悬空的镜像
docker image prune
#清理未被任何容器使用的卷
docker volume prune
#清理未被任何容器使用的网络
docker network prune卷被哪些容器使用
docker ps -a --filter volume=VOLUME_NAME_OR_MOUNT_POINT数据卷
说明 - 容器内部都是最小化安装的,不会安装vi等工具。 - 所以容器中的工作内容最好通过卷的形式映射到宿主机中。
volume
是一个虚拟目录,是内容目录与宿主机目录之间映射的桥梁
数据卷目录固定存放在宿主机
/var/lib/docker/volumes 下面
volumes下建立目录例如: html/_data 对应html数据卷 conf/_data 对应conf数据卷
命令
docker volume create
创建卷
docker volume ls
查看
docker volume rm
删除
docker volume prune
删除没有使用的本地卷
docker volume inspect
查看某个数据卷的详细信息
docker run
-v 数据卷名字:容器内目录
⚠️:-v 卷名:容器目录,直接写名字:就是卷名,使用绝对或相对路径就是挂载本地目录
-v nginx-html:/usr/share/nginx/html 「使用卷: nginx-html」
-v ./nginx-html:/usr/share/nginx/html 「挂载本地目录: ./nginx-html」
⚠️:数据卷不存在会自动创建,并会拷贝容器中的内容
用途⚠️:可以使用没有的卷做映射,这样可以把容器里的数据和配置文件拿到
docker inspect 容器名
查看容器详情
匿名卷
不是我们创建的,容器创建的时候默认创建的卷叫匿名卷,名字是一长串。
mysql: 创建mysql容器的时候,会自动创建一个存储数据库数据的卷
删除容器的时候数据卷不会被删除
也就是说数据会被永久保留
本地目录挂载
docker run -v 本地目录:容器内目录
与挂载数据卷方法相同,只是使用的本地目录
目录必须使用路径开头,可以是绝对路径或相对路径。
例如: -v mysql:/var/lib/mysql 这就是挂载一个数据卷 -v ./mysql:/var/lib/mysql 就是挂载本地目录
步骤,查看映像官方文档,把所有需要的目录都挂载到本地。

mysql 挂载本地目录

本地文件和文件夹挂载到容器的文件关系
背景介绍
docker volume 可以使我们在启动docker容器时,动态的挂载一些文件(如配置文件), 以覆盖镜像中原有的文件,但是,挂载一个主机上尚不存在的文件夹或者文件到容器中会怎样呢?这里特意做了一下实践,记录实验结果如下:
「文件夹挂载」
docker在文件夹挂载上的行为是统一的,具体表现为:
若文件夹不存在,则先创建出文件夹(若为多层文件夹,则递归创建)
用host上的文件夹内容覆盖container中的文件夹内容
docker run -v /path-to-folder/A:/path-to-folder/B test-image详细说明如下:
host上文件夹存在,且非空
无论container中的文件夹B是否存在, A都会完全覆盖B的内容
host上文件夹存在,但为空
container中对应的文件夹内容被清空
host上文件夹不存在
container中对应的文件夹内容被清空
总结
host上文件夹一定会覆盖container中文件夹:
「文件挂载」
文件挂载与文件夹挂载最大的不同点在于:
⚠️:docker 禁止用主机上不存在的文件挂载到container中已经存在的文件
文件挂载不会对同一文件夹下的其他文件产生任何影响
除此之外, 其覆盖行为与文件夹挂载一致,即:
用host上的文件的内容覆盖container中的文件的内容
docker run -v /path-to-folder/non-existent-config.js:/path-to-folder/config.js test-image # forbidden详细说明如下:
host上文件不存在
host上文件存在
总结
host上文件一定会覆盖container中文件夹
结论
「文件夹挂载」
允许不存在的文件夹或者存在的空文件夹挂载进container, container中对应的文件夹将被清空
非空文件夹挂载进container将会覆盖container中原有文件夹
「文件挂载」
禁止将不存在的文件挂载进container中已经存在的文件上
存在的文件挂载进container中将会覆盖container中对应的文件, 若文件不存在则新建
应用场景
从上面的分析可知,文件夹挂载以整个文件夹为单位进行文件覆盖,故可在需要将大量文件挂载进container时使用,另外,如果挂载一个空文件夹或者不存在的文件夹,一般是做逆向使用: 即容器启动后,可能会在容器内挂载点的文件夹下生成一些文件(如日志),此时,在对应的host上的文件夹内就能直接看到。
文件挂载由于只会覆盖单个文件而不会影响container中同一文件夹下的其他文件,常常被用来挂载配置文件,以在运行时,动态的修改默认配置。
特别注意
容器中类似mysql,redis这样的数据目录可以映射到宿主机目录的原因是,目录里的内容不是在容器启动前就存在的,而是在容器启动后生成的。
下面是mysql容器运行的时候对数据目录的处理:
内容来自deepseek
当您运行 MySQL 的 Docker 容器时,数据目录的初始化过程会根据不同场景(首次运行/非首次运行)和配置方式(环境变量/挂载卷/Dockerfile 等)有所差异。以下是详细流程:
---
### 1. **首次运行容器时的初始化逻辑**
MySQL 官方镜像(如 `mysql:8.0`)的 `ENTRYPOINT` 脚本会执行以下关键步骤:
#### **(1) 检查数据目录是否为空**
- **目标目录**:默认是 `/var/lib/mysql`(可通过 `$MYSQL_DATA_DIR` 自定义)。
- **如果目录为空**(如首次运行或挂载了空目录):
- 调用 `mysql_install_db`(MySQL 5.7 及以下)或 `mysqld --initialize-insecure`(MySQL 8.0+)初始化数据目录。
- 生成系统表(如 `mysql`、`sys`、`performance_schema` 等)。
- 创建默认用户(`root@localhost`)并设置初始密码(通过 `$MYSQL_ROOT_PASSWORD` 或随机密码)。
#### **(2) 应用自定义配置**
- 通过环境变量(如 `$MYSQL_DATABASE`、`$MYSQL_USER` 等)创建指定的数据库和用户。
- 执行 `/docker-entrypoint-initdb.d/` 下的脚本(`.sh`/`.sql`/`.sql.gz`),用于导入数据或自定义配置。
#### **(3) 启动 MySQL 服务**
- 最终以 `mysqld` 启动服务,数据目录初始化完成。
---
### 2. **非首次运行的行为**
- **如果数据目录已存在且非空**(如挂载了已有数据的宿主机目录或复用卷):
- **跳过初始化**,直接启动 `mysqld`。
- 原有数据(包括数据库、用户、权限等)会被保留。
---
### 3. **关键配置方式与示例**
#### **(1) 使用环境变量初始化**
bash
docker run -d --name mysql \
-e MYSQL_ROOT_PASSWORD=123456 \
-e MYSQL_DATABASE=myapp \
-e MYSQL_USER=user \
-e MYSQL_PASSWORD=pass \
mysql:8.0
- 首次运行时自动初始化数据目录并创建指定数据库和用户。
#### **(2) 挂载宿主机目录或卷**
bash
# 挂载宿主机目录(需确保目录权限正确)
docker run -d --name mysql \
-v /path/on/host:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=123456 \
mysql:8.0
# 使用命名卷(推荐)
docker volume create mysql_data
docker run -d --name mysql \
-v mysql_data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=123456 \
mysql:8.0
- **首次挂载空目录**:容器会初始化数据到宿主机目录。
- **挂载已有数据目录**:直接使用现有数据。
#### **(3) 通过 `/docker-entrypoint-initdb.d/` 初始化数据**
bash
# 将 SQL 脚本或 Shell 脚本挂载到初始化目录
docker run -d --name mysql \
-v ./init-scripts:/docker-entrypoint-initdb.d \
-e MYSQL_ROOT_PASSWORD=123456 \
mysql:8.0
- 脚本按字母顺序执行(例如 `01-create-tables.sql`、`02-insert-data.sh`)。
---
### 4. **数据目录权限问题**
MySQL 容器默认以 `mysql` 用户(UID: 999)运行,需确保挂载的宿主机目录权限正确:
bash
mkdir -p /path/on/host
chown -R 999:999 /path/on/host # 或 chmod 777(测试用途)
---
### 5. **调试技巧**
- **查看初始化日志**:
bash
docker logs mysql # 观察首次运行的初始化输出
- **手动进入容器检查**:
bash
docker exec -it mysql bash
ls /var/lib/mysql # 查看数据文件
---
### 总结表
| 场景 | 行为 |
|--------------------------|----------------------------------------------------------------------|
| **首次运行 + 空目录** | 初始化数据目录,创建系统库和默认用户,执行自定义脚本。 |
| **首次运行 + 非空目录** | 直接使用现有数据,跳过初始化。 |
| **非首次运行** | 直接启动 `mysqld`,保留原有数据。 |
| **挂载 `initdb.d` 脚本** | 仅在首次初始化时执行(数据目录为空时)。 |
通过合理组合环境变量、卷挂载和初始化脚本,可以灵活控制 MySQL 容器的数据初始化流程。Dockerfile
制作自己的镜像 
⚠️:我们自己制作好的项目做成镜像需要以下内容:
安装JRE并配置环境变量
拷贝JAR包
运行JAR做好镜像后就可以直接发布。

Dockerfile 「就是一个文件,包含一个个的指令,用于定义如何构建Docker镜像。」
常见命令

FROM
指定基础镜像
FROM centos:6
ENV
设置环境变量,可以在后面指令使用
ENV key value
COPY
拷贝本地文件到镜像指定的目录
COPY ./jrell1.tar.gz /tmp
RUN
执行Linux的shell命令,一般是安装过程命令
RUN targ -zxvf /tmp/jre11.tar.gz && EXPORTS path=/tmp/jre11:$path
RUN yum -y install vim
安装vim
EXPOSE
指定容器运行时监听的端口,是给镜像使用者看的
EXPOSE 8080
ENTRYPOINT
镜像中应用的启动命令,容器运行时调用
ENTRYPOINT java -jar xx.jar
WORKDIR
设置工作目录
WORKDIR /app
MAINTAINER
指定维护者信息
可以包括:姓名 邮箱等
ADD
该命令将复制指定的 路径下内容到镜像中的 路径下
⚠️:ADD 和 COPY 的区别和使用场景
ADD 支持添加远程 url 和自动提取压缩格式的文件,COPY 只允许从本机中复制文件
COPY 支持从其他构建阶段中复制源文件(–from)
根据官方 Dockerfile 最佳实践,除非真的需要从远程 url 添加文件或自动提取压缩文件才用 ADD,其他情况一律使用 COPY
⚠️:ADD 从远程 url 获取文件和复制的效果并不理想,因为该文件会增加 Docker Image 最终的大小。相反,应该使用 curl huo wget 来获取远程文件,然后在不需要它时进行删除
VOLUME
创建一个匿名数据卷挂载点
官方详细文档
例子:从ubuntu 构建一个java运行项目
#指定基础镜像
FROM ubuntu:16.04
#配置环境变量,JDK的安装目录,容器内识趣
ENV JAVA_DIR=/usr/local
#拷贝jdk和java项目的包
COPY ./jdk8.tar.gz $JAVA_DIR/
COPY ./docker-demo.jar /tmp/app.jar
#安装 jdk
RUN cd $JAVA_DIR \
&& tar -xf ./jdk8.tar.gz \
&& mv ./jdk1.8.0_144 ./java8
#配置环境变量
ENV JAVA_HOME=$JAVA_DIR/java8
ENV PATH=$JAVA_HOME/bin
#入口,java项目的启动命令
ENTRYPOINT ["java", "-jar", "/tmp/app.jar"]例子:从jdk镜像构建一个java项目
方法一: 直接把jar文件构拷贝到包中。 此方法适合发布不修改的jar项目。
#基础镜像
FROM openjdk:11.0-jre-buster
#设置时区,默认时区不是东八区
ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
#拷贝jar包
COPY docker-demo.jar /app.jar
#入口
ENTRYPOINT ["java", "-jar", "/app.jar"]方法二:
首先构建一个openjdk镜像
#Dockerfile
#基础镜像
FROM openjdk:11.0-jre-buster
#设置时区,默认时区不是东八区
ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone用run构建容器
#run 后面可以直接跟执行命令,这样可以把jar文件映射进去,然后启动执行
sudo docker run -d --name app.jar -p 8080:8080 -v ./app:/app openjdk11:1.0 java -jar /app/app.jar
#更新jar包: 只需要stop容器,更新jar文件,start容器即可。命令
docker build -t myImage:1.0 .
-t tag的缩写,后面是名称:tag . 在最后,指定dockerfile文件所在的目录 注意COPY中使用的路径都是相对这个路径的
建立好的镜像就在docker中,可以使用docker images 查看
配置文件名: Dockerfile
容器网络互联
docker inspect 容器名
可以查看容器的ip地址,每个容器都有自己的ip地址
初始网络
安装docker的时候会在机器上安装一个虚拟网卡:名字 docker0 并创建一个虚拟的网桥:172.17.0.1/16 【16】前16位不能动
容器之间是可以互相连通的
容器的ip地址不是固定的,需要做自定义网络,可以通过容器名访问
不能使用IP地址链接,ip地址是会变的
同一网桥中的容器可以互相访问,不是同一网桥的不能互相访问。
⚠️:默认网络不能通过容器名称进行互相访问,ip地址可以,但IP地址是变化的不准确不能使用

自定义网桥
必须是自定义网络中才可以通过容器名称进行访问
默认网络是没有这个功能的
所以要做容器之间的网络通信,就必须要自定义网络

命令
docker network create
创建一个网络
创建一个网络会在宿主机上多出一个虚拟网卡,增加一个网段,默认是网桥的模式
docker network ls
查看所有网络
docker network rm
删除指定网络
docker network prune
删除未使用的网络
docker network connect
使指定容器链接加入网络
docker network connect 网络名字 容器名字
容器加入网络后,会同时在两个网络中
docker network disconnect
使指定容器链接断开某网络
docker network inspect
查看网络详细信息
docker run --network 网络名称
创建的容器直接在这个网络中
项目的部署 「docker compose」
docker-compose.yml
version 可以设置 2.x 和 3.x 「这个是旧版了,version已经不需要设置了」
version 现代docker compose不需要设置 「也就是 compose v2版本以上」
docker compose 可以运行就是v2版本的compose,不需要设置version
docker compose version 查看版本信息
模版

docker run 和docker-compose.yml 语法之间的对比

entrypoint 定义容器启动时运行的主程序(可执行文件或脚本)。
command 作为参数传递给 entrypoint(相当于 ENTRYPOINT 的默认参数)。
services:
webapp:
image: nginx:alpine
entrypoint: ["/run.sh"]
command: ["arg1", "arg2", "arg3"]执行命令为: /run.sh arg1 arg2 arg3
关键点
如果 entrypoint 是列表形式(如 ["/docker-entrypoint.sh"]):
Docker 会直接执行 /docker-entrypoint.sh,并附加 command 作为参数。
不会 通过 shell 解析(如 sh -c),所以环境变量替换等 shell 功能不会自动生效。
如果 entrypoint 是字符串形式(如 "/docker-entrypoint.sh"):
Docker 会通过 /bin/sh -c 执行,支持 shell 功能(如变量替换 $VAR)。
但推荐使用列表形式以避免 shell 解析的意外行为。
如果 entrypoint 未设置:
会使用镜像中定义的 ENTRYPOINT(来自 Dockerfile)。
command 会完全覆盖 Dockerfile 的 CMD。
容器启动执行的命令用参数 command:进行配置
services:
app.jar:
image: openjdk11:1.0
container_name: app.jar
volumes:
- "./app:/app"
command: java -jar /app/app.jar
networks:
- net
networks:
net:
external: true #使用已经创建的网络限制容器使用资源
在 Docker 中,可以通过多种方式限制容器使用的资源(CPU、内存、磁盘 I/O 等)。以下是常用的资源限制方法:
内存限制
限制容器最大内存使用量:
docker run -it --memory="1g" --memory-swap="2g" ubuntu--memory:容器可用的物理内存上限(例如1g表示 1GB)。--memory-swap:内存+交换分区的总限制(需 ≥--memory)。--memory-swappiness:控制交换分区的使用比例(0-100,0 表示禁用交换)。
防止容器耗尽宿主机内存:
docker run -it --memory="500m" --oom-kill-disable ubuntu--oom-kill-disable:禁止 OOM Killer 终止容器进程(慎用)。
CPU 限制**
限制容器使用的 CPU 核心数:
docker run -it --cpus="1.5" ubuntu--cpus:限制容器最多使用 1.5 个 CPU 核心。
绑定到指定 CPU 核心:
docker run -it --cpuset-cpus="0,2" ubuntu--cpuset-cpus:限制容器只运行在 CPU 0 和 2 上。
按权重分配 CPU 时间:
docker run -it --cpu-shares="512" ubuntu--cpu-shares:默认值为 1024,权重越高分配的 CPU 时间越多(相对比例)。
磁盘 I/O 限制
限制磁盘读写带宽:
docker run -it \
--device-read-bps="/dev/sda:1mb" \
--device-write-bps="/dev/sda:1mb" \
--device-read-iops="/dev/sda:100" \
--device-write-iops="/dev/sda:100" \
ubuntu--device-read-bps/--device-write-bps:限制每秒读写带宽(例如1mb)。--device-read-iops/--device-write-iops:限制每秒 IO 操作次数。
进程数限制(PID 限制)
docker run -it --pids-limit=100 ubuntu--pids-limit:限制容器内最大进程数(防止 fork 炸弹)。
使用
docker-compose配置资源限制**
在 docker-compose.yml 中示例:
services:
app:
image: ubuntu
deploy:
resources:
limits:
cpus: "0.5"
memory: 500M
reservations:
memory: 200Mlimits:硬性限制。reservations:预留资源(仅 Swarm 模式下有效)。
动态查看资源使用情况
docker stats [容器名]实时监控容器的 CPU、内存、网络等资源占用。
注意事项
资源限制的优先级:部分参数(如
--memory)是硬限制,超出会导致容器被终止。Swarm/Kubernetes:在生产环境中,通常结合编排工具(如 Swarm/K8s)实现更精细的资源管理。
性能影响:过度限制可能导致容器性能下降,需根据实际需求调整。
建议: 不限制容器资源,而是通过监控报警的方式进行管理。
多容器


depends_on 依赖哪个容器
配置文件和镜像生成
#docker-compose.yml
services:
ruoyi-mysql:
container_name: ruoyi-mysql
#设置了image映像得到过程如下:
#1. 从本地查找镜像是否存在,存在直接使用
#2. 从中央仓库查找镜像是否存在,存在下载
#3. 中央仓库没有,配置文件中有build,则从build指定的配置文件中创建。
#4. 如果没有build则找不到映像。
#没有设置image映像的得到过程:
#1. 通过build指定的dockerfile配置文件,生成镜像。
# 镜像名称一般是项目名称「执行docker compose时候指定的」-服务名称。
#建议:
#1. 非必要不要自己通过dockerfile建立映像,尽量使用run的参数「或者compose配置文件」去生成。
#2. 如果一定要创建映像文件,则尽量把image的名字起的不重复防止中央仓库中有而下载。
# 更好的办法是不指定image的名字,而是up的时候现生成一个映像。
# image: mysql:5.7
build:
context: .
dockerfile: mysql-dockerfile
ports:
- "3306:3306"
volumes:
- ./mysql/conf:/etc/mysql/conf.d
- ./mysql/logs:/logs
- ./mysql/data:/var/lib/mysql
command: [
'mysqld',
'--innodb-buffer-pool-size=80M',
'--character-set-server=utf8mb4',
'--collation-server=utf8mb4_unicode_ci',
'--default-time-zone=+8:00',
'--lower-case-table-names=1'
]
environment:
MYSQL_DATABASE: 'ry-vue'
MYSQL_ROOT_PASSWORD: passwordlinks、external-links、network的关系
external_links 和 links 都是用于在 Docker 中建立容器之间的链接关系,但它们在使用方式和适用范围上有一些区别。
语法和使用方式:
links:links是 Docker Compose 中的字段,用于在同一 Compose 文件中定义容器之间的链接关系。它使用的语法是将容器名称指定为链接的目标,并可以为链接指定别名。例如:links: - container1:alias1。external_links:external_links是 Docker Compose 中的字段,用于在容器之间建立链接关系,但链接的目标容器不一定在同一 Compose 文件中定义。它使用的语法是将外部容器的名称指定为链接的目标,并可以为链接指定别名。例如:external_links: - container2:alias2。
适用范围:
links:links字段适用于同一 Docker Compose 文件中的容器之间的链接关系。它使得容器可以通过链接的别名来进行网络连接和服务访问。external_links:external_links字段适用于在不同 Docker Compose 文件、甚至不同项目中的容器之间建立链接关系。它使得容器可以通过链接的别名来访问在其他 Compose 文件或项目中定义的容器服务。
推荐使用:
links:在较新的 Docker Compose 版本中,links已经被弃用,不再推荐使用。取而代之的是使用自定义网络(networks)来定义容器之间的关联关系。external_links:虽然external_links仍然可用,但在较新的 Docker Compose 版本中,也推荐使用自定义网络(networks)来定义容器之间的链接关系,以提供更灵活和可控的网络连接方式。
总结来说,links 用于在同一 Compose 文件中定义容器之间的链接关系,而 external_links 用于在不同 Compose 文件或项目中的容器之间建立链接关系。然而,推荐使用自定义网络(networks)来取代 links 和 external_links,以提供更好的网络管理和连接方式。
docker compose 命令

#up 一键启动
#down 一键删除
docker compose up -d #-d后台运行,-d 一定要放在up的后面
sudo docker compose down #容器、网络会被删除,下砸的影像不会被删除docker compose 多服务器部署
可以做单服务器多实例的负载均衡
Docker Compose 本身不支持跨多个服务器分布式部署。如果你想要在多个服务器上运行容器,你需要在每台服务器上分别运行Docker和Docker Compose,并在每台服务器上定义相同的服务。 但是,你可以使用Docker Swarm或Kubernetes这样的编排工具来在多个服务器上部署容器,并且可以通过编排工具来管理这些容器的分布式部署。
备份
- 使用以下命令备份所有正在运行的容器及其卷
备份前停止所有的容器 docker stop $(docker ps -aq)
docker ps -a -q | xargs -I {} docker export {} -o container_{}.tar docker volume ls -q | xargs -I {} docker run --rm -v {}:/data -v $(pwd):/backup ubuntu tar czf /backup/volume_{}.tar.gz /datadocker export 是 Docker 的一个命令,用于将容器的文件系统导出为一个 tar 归档文件,但不包含容器的元数据、日志或运行状态信息。它主要用于持久化容器的文件系统快照,适用于数据备份或迁移场景。
#基本用法 docker export [OPTIONS] CONTAINER > output.tar #或 docker export [OPTIONS] CONTAINER -o output.tar #CONTAINER:可以是容器名称或 ID。 #output.tar 或 -o output.tar:将导出的内容保存为 .tar 文件。与 docker save 的区别
与 docker commit 的区别
备份配置文件
#Linux 系统 sudo cp /etc/docker/daemon.json ~/docker_daemon_backup.json备份 Docker 数据目录
#通常位于 /var/lib/docker #可以使用 docker info 查看 sudo docker info |grep "Docker Root Dir" sudo tar czf docker_data_backup.tar.gz /var/lib/docker
# docker 常用命令
## 资料
- 官方文档
- [https://docs.docker.com](https://docs.docker.com)
## docker 服务操作
- sudo systemctl start docker
- sudo systemctl stop docker #停止
- sudo systemctl restart docker #重新启动
- sudo systemctl enable docker #开机自动启动
## 设置镜像加速
- ⚠️:此处以阿里云举例「加速地址只能在自己的云平台中使用」
- 阿里云 aliyun.com
- 登录 阿里云
- 选择菜单->【产品】-> 【容器】-> 【容器镜像服务 ACR】-> 点击按钮【管理控制台】-> 左侧菜单【镜像工具->镜像加速器】-> 会看到一个镜像加速地址
- 不收费
- 加速地址: [https://iiesyla9.mirror.aliyuncs.com](https://iiesyla9.mirror.aliyuncs.com)
- 具体配置方法下面有详细的说明
```bash
#如果没有/etc/docker目录就建立,没有daemon.json文件就建立。
#此处举例为没有这个目录和文件
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{ "registry-mirrors": ["https://iiesyla9.mirror.aliyuncs.com"] }
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
```
## 查看版本
- docker --version 「-v」 只能查看版本号,不能看出来是ce 还是 io 版本。
- docker version 可以查看时ce还是io版本。
## 配置文件位置
- ⚠️:没有 /etc/docker 目录和daemon.json 文件也是正常的。
- linux
- /etc/docker/daemon.json
- mac
- ~/.docker/config.json
## 根目录存储位置
- linux
```bash
docker info
#命令,里面有一项 Docker Root Dir: /var/lib/docker
#映像文件存储位置默认路径: /var/lib/docker
```
- mac
- 在docker的图形设置界面中,有一个磁盘的选项里面有具体大小的配置,是一个很大的raw文件。
## 查看容器详细信息
- 命令: docker inspect 容器名
- Mounts:挂载的卷
- Networks:网络信息
- Ports:映射的端口
- Config:包括:环境变量、Cmd、使用的映像、EntryPoint「入口命令」、Volumes等
## 监控docker
```bash
#类似linux的top命令
docker stats
```
## 镜像操作
- docker pull 镜像名称 「拉取镜像」
- docker images 「查看本地镜像列表」
- docker rmi 镜像名字 「删除指定镜像」
- docker push 「推镜像到镜像仓库」
## 容器相关操作
- docker create 「创建容器」
```bash
#使用docker镜像nginx:latest创建一个容器,并将容器命名为myrunoob
docker create --name myrunoob nginx:latest
```
- docker run 「创建并运行一个容器」
- -d : 容器后台运行;不加这个参数会卡住在控制台,停止后进程会停止
- --name 指定容器的名称
- -p 宿主机端口:容器内端口
- 例如: -p 3307:3306
- -e 环境变量,不同镜像的变量不同
- mysql 是镜像的名字
- 完整写法: mysql:5.7
- tag不写就是 lastest
- -v 宿主机目录:容器内部目录
- 宿主机目录没有:自动创建
- 容器内部目录没有:自动创建
- 都没有:同时创建
- -w
- 指定容器内部的工作目录
- docker stop 容器 「停止容器的运行,并没有删除容器」
- docker start 容器 「启动 容器进程」
- docker ps
- 查看容器状态,默认只显示运行的容器 -a 查看所有容器
- 已表格的方式查看
- docker rm
- 删除容器 容器中的数据会被删除
- -f 强制删除容器,可以删除运行的容器
- docker exec
- 执行命令进入容器内步
- -it 进入交互状态
- docker save 「可以写多个image,这样就把多个镜像保存了」
```bash
docker save -o 输出文件名.tar ngnix:latest
```
- docker load 「不用写映像的名字,文件中自己会指定」
```bash
docker load -i file.tar
```
- docker logs 「查看容器日志」
```bash
#查看日志 -f 是follow的缩写,查看日志不停,持续输出
docker logs -f 容器名
```
- docker cp 「拷贝容器里面的文件到宿主机 nginx 是容器名称」
```bash
docker cp nginx:/etc/nginx/nginx.conf /home/nginx/conf/nginx.conf
```
## 帮助
- docker 命令 --help
```bash
#查看save命令的帮助
dockder save --help
#查看run命令的帮助
docker run --help
```
## 磁盘的使用情况
- docker system df
## 清理镜像、容器、卷、网络
- 清理 「镜像、容器、卷、网络的清理」
- [https://blog.51cto.com/u_16175493/8099417](https://blog.51cto.com/u_16175493/8099417)
- sudo docker image prune
- 清理悬空镜像
- sudo docker system prune -a
- 清理未使用的镜像、容器、网络和卷
- 加上 `-a` 参数后,命令还会删除所有未被容器使用的悬空镜像(dangling 和非 dangling 镜像都会被清理)。
```bash
#清理停止的容器
docker container prune
#清理悬空的镜像
docker image prune
#清理未被任何容器使用的卷
docker volume prune
#清理未被任何容器使用的网络
docker network prune
```
## 卷被哪些容器使用
```bash
docker ps -a --filter volume=VOLUME_NAME_OR_MOUNT_POINT
```
## 数据卷
- 说明 - 容器内部都是最小化安装的,不会安装vi等工具。 - 所以容器中的工作内容最好通过卷的形式映射到宿主机中。
- volume
- 是一个虚拟目录,是内容目录与宿主机目录之间映射的桥梁
- 数据卷目录固定存放在宿主机
- /var/lib/docker/volumes 下面
- volumes下建立目录例如: html/_data 对应html数据卷 conf/_data 对应conf数据卷
- 命令
- docker volume create
- 创建卷
- docker volume ls
- 查看
- docker volume rm
- 删除
- docker volume prune
- 删除没有使用的本地卷
- docker volume inspect
- 查看某个数据卷的详细信息
- docker run
- -v 数据卷名字:容器内目录
- ⚠️:-v 卷名:容器目录,直接写名字:就是卷名,使用绝对或相对路径就是挂载本地目录
- -v nginx-html:/usr/share/nginx/html 「使用卷: nginx-html」
- -v ./nginx-html:/usr/share/nginx/html 「挂载本地目录: ./nginx-html」
- ⚠️:数据卷不存在会自动创建,并会拷贝容器中的内容
- 用途⚠️:可以使用没有的卷做映射,这样可以把容器里的数据和配置文件拿到
- docker inspect 容器名
- 查看容器详情
- 匿名卷
- 不是我们创建的,容器创建的时候默认创建的卷叫匿名卷,名字是一长串。
- mysql: 创建mysql容器的时候,会自动创建一个存储数据库数据的卷
- 删除容器的时候数据卷不会被删除
- 也就是说数据会被永久保留
## 本地目录挂载
- docker run -v 本地目录:容器内目录
- 与挂载数据卷方法相同,只是使用的本地目录
- 目录必须使用路径开头,可以是绝对路径或相对路径。
- 例如: -v mysql:/var/lib/mysql 这就是挂载一个数据卷 -v ./mysql:/var/lib/mysql 就是挂载本地目录
- 步骤,查看映像官方文档,把所有需要的目录都挂载到本地。 
- mysql 挂载本地目录

### 本地文件和文件夹挂载到容器的文件关系
**背景介绍**
docker volume 可以使我们在启动docker容器时,动态的挂载一些文件(如配置文件), 以覆盖镜像中原有的文件,但是,挂载一个主机上尚不存在的文件夹或者文件到容器中会怎样呢?这里特意做了一下实践,记录实验结果如下:
**「文件夹挂载」**
docker在文件夹挂载上的行为是统一的,具体表现为:
- 若文件夹不存在,则先创建出文件夹(若为多层文件夹,则递归创建)
- 用host上的文件夹内容覆盖container中的文件夹内容
```bash
docker run -v /path-to-folder/A:/path-to-folder/B test-image
```
详细说明如下:
**host上文件夹存在,且非空**

> 无论container中的文件夹B是否存在, A都会完全覆盖B的内容
**host上文件夹存在,但为空**

> container中对应的文件夹内容被清空
**host上文件夹不存在**

> container中对应的文件夹内容被清空
**总结**
host上文件夹一定会覆盖container中文件夹:

---
**「文件挂载」**
文件挂载与文件夹挂载最大的不同点在于:
- ⚠️:docker 禁止用主机上不存在的文件挂载到container中已经存在的文件
- 文件挂载不会对同一文件夹下的其他文件产生任何影响
除此之外, 其覆盖行为与文件夹挂载一致,即:
- 用host上的文件的内容覆盖container中的文件的内容
```bash
docker run -v /path-to-folder/non-existent-config.js:/path-to-folder/config.js test-image # forbidden
```
详细说明如下:
- host上文件不存在
- 
- host上文件存在
- 
- 总结
host上文件一定会覆盖container中文件夹

**结论**
「文件夹挂载」
- 允许不存在的文件夹或者存在的空文件夹挂载进container, container中对应的文件夹将被清空
- 非空文件夹挂载进container将会覆盖container中原有文件夹
「文件挂载」
- 禁止将不存在的文件挂载进container中已经存在的文件上
- 存在的文件挂载进container中将会覆盖container中对应的文件, 若文件不存在则新建
**应用场景**
1. 从上面的分析可知,文件夹挂载以整个文件夹为单位进行文件覆盖,故可在需要将大量文件挂载进container时使用,另外,如果挂载一个空文件夹或者不存在的文件夹,一般是做逆向使用: 即容器启动后,可能会在容器内挂载点的文件夹下生成一些文件(如日志),此时,在对应的host上的文件夹内就能直接看到。
2. 文件挂载由于只会覆盖单个文件而不会影响container中同一文件夹下的其他文件,常常被用来挂载配置文件,以在运行时,动态的修改默认配置。
**特别注意**
容器中类似mysql,redis这样的数据目录可以映射到宿主机目录的原因是,**目录里的内容不是在容器启动前就存在的,而是在容器启动后生成的**。
- 下面是mysql容器运行的时候对数据目录的处理:
> 内容来自deepseek
```markdown
当您运行 MySQL 的 Docker 容器时,数据目录的初始化过程会根据不同场景(首次运行/非首次运行)和配置方式(环境变量/挂载卷/Dockerfile 等)有所差异。以下是详细流程:
---
### 1. **首次运行容器时的初始化逻辑**
MySQL 官方镜像(如 `mysql:8.0`)的 `ENTRYPOINT` 脚本会执行以下关键步骤:
#### **(1) 检查数据目录是否为空**
- **目标目录**:默认是 `/var/lib/mysql`(可通过 `$MYSQL_DATA_DIR` 自定义)。
- **如果目录为空**(如首次运行或挂载了空目录):
- 调用 `mysql_install_db`(MySQL 5.7 及以下)或 `mysqld --initialize-insecure`(MySQL 8.0+)初始化数据目录。
- 生成系统表(如 `mysql`、`sys`、`performance_schema` 等)。
- 创建默认用户(`root@localhost`)并设置初始密码(通过 `$MYSQL_ROOT_PASSWORD` 或随机密码)。
#### **(2) 应用自定义配置**
- 通过环境变量(如 `$MYSQL_DATABASE`、`$MYSQL_USER` 等)创建指定的数据库和用户。
- 执行 `/docker-entrypoint-initdb.d/` 下的脚本(`.sh`/`.sql`/`.sql.gz`),用于导入数据或自定义配置。
#### **(3) 启动 MySQL 服务**
- 最终以 `mysqld` 启动服务,数据目录初始化完成。
---
### 2. **非首次运行的行为**
- **如果数据目录已存在且非空**(如挂载了已有数据的宿主机目录或复用卷):
- **跳过初始化**,直接启动 `mysqld`。
- 原有数据(包括数据库、用户、权限等)会被保留。
---
### 3. **关键配置方式与示例**
#### **(1) 使用环境变量初始化**
bash
docker run -d --name mysql \
-e MYSQL_ROOT_PASSWORD=123456 \
-e MYSQL_DATABASE=myapp \
-e MYSQL_USER=user \
-e MYSQL_PASSWORD=pass \
mysql:8.0
- 首次运行时自动初始化数据目录并创建指定数据库和用户。
#### **(2) 挂载宿主机目录或卷**
bash
# 挂载宿主机目录(需确保目录权限正确)
docker run -d --name mysql \
-v /path/on/host:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=123456 \
mysql:8.0
# 使用命名卷(推荐)
docker volume create mysql_data
docker run -d --name mysql \
-v mysql_data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=123456 \
mysql:8.0
- **首次挂载空目录**:容器会初始化数据到宿主机目录。
- **挂载已有数据目录**:直接使用现有数据。
#### **(3) 通过 `/docker-entrypoint-initdb.d/` 初始化数据**
bash
# 将 SQL 脚本或 Shell 脚本挂载到初始化目录
docker run -d --name mysql \
-v ./init-scripts:/docker-entrypoint-initdb.d \
-e MYSQL_ROOT_PASSWORD=123456 \
mysql:8.0
- 脚本按字母顺序执行(例如 `01-create-tables.sql`、`02-insert-data.sh`)。
---
### 4. **数据目录权限问题**
MySQL 容器默认以 `mysql` 用户(UID: 999)运行,需确保挂载的宿主机目录权限正确:
bash
mkdir -p /path/on/host
chown -R 999:999 /path/on/host # 或 chmod 777(测试用途)
---
### 5. **调试技巧**
- **查看初始化日志**:
bash
docker logs mysql # 观察首次运行的初始化输出
- **手动进入容器检查**:
bash
docker exec -it mysql bash
ls /var/lib/mysql # 查看数据文件
---
### 总结表
| 场景 | 行为 |
|--------------------------|----------------------------------------------------------------------|
| **首次运行 + 空目录** | 初始化数据目录,创建系统库和默认用户,执行自定义脚本。 |
| **首次运行 + 非空目录** | 直接使用现有数据,跳过初始化。 |
| **非首次运行** | 直接启动 `mysqld`,保留原有数据。 |
| **挂载 `initdb.d` 脚本** | 仅在首次初始化时执行(数据目录为空时)。 |
通过合理组合环境变量、卷挂载和初始化脚本,可以灵活控制 MySQL 容器的数据初始化流程。
```
## Dockerfile
制作自己的镜像 
⚠️:我们自己制作好的项目做成镜像需要以下内容:
1. 安装JRE并配置环境变量
2. 拷贝JAR包
3. 运行JAR做好镜像后就可以直接发布。
- Dockerfile 「就是一个文件,包含一个个的指令,用于定义如何构建Docker镜像。」
- 常见命令

- FROM
- 指定基础镜像
- FROM centos:6
- ENV
- 设置环境变量,可以在后面指令使用
- ENV key value
- COPY
- 拷贝本地文件到镜像指定的目录
- COPY ./jrell1.tar.gz /tmp
- RUN
- 执行Linux的shell命令,一般是安装过程命令
- RUN targ -zxvf /tmp/jre11.tar.gz && EXPORTS path=/tmp/jre11:$path
- RUN yum -y install vim
- 安装vim
- EXPOSE
- 指定容器运行时监听的端口,是给镜像使用者看的
- EXPOSE 8080
- ENTRYPOINT
- 镜像中应用的启动命令,容器运行时调用
- ENTRYPOINT java -jar xx.jar
- WORKDIR
- 设置工作目录
- WORKDIR /app
- MAINTAINER
- 指定维护者信息
- 可以包括:姓名 邮箱等
- ADD
- 该命令将复制指定的 路径下内容到镜像中的 路径下
- ⚠️:ADD 和 COPY 的区别和使用场景
- ADD 支持添加远程 url 和自动提取压缩格式的文件,COPY 只允许从本机中复制文件
- COPY 支持从其他构建阶段中复制源文件(–from)
- 根据官方 Dockerfile 最佳实践,除非真的需要从远程 url 添加文件或自动提取压缩文件才用 ADD,其他情况一律使用 COPY
- ⚠️:ADD 从远程 url 获取文件和复制的效果并不理想,因为该文件会增加 Docker Image 最终的大小。相反,应该使用 curl huo wget 来获取远程文件,然后在不需要它时进行删除
- VOLUME
- 创建一个匿名数据卷挂载点
- 官方详细文档
- [https://docs.docker.com/engine/reference/builder](https://docs.docker.com/engine/reference/builder)
- 例子:从ubuntu 构建一个java运行项目
```yml
#指定基础镜像
FROM ubuntu:16.04
#配置环境变量,JDK的安装目录,容器内识趣
ENV JAVA_DIR=/usr/local
#拷贝jdk和java项目的包
COPY ./jdk8.tar.gz $JAVA_DIR/
COPY ./docker-demo.jar /tmp/app.jar
#安装 jdk
RUN cd $JAVA_DIR \
&& tar -xf ./jdk8.tar.gz \
&& mv ./jdk1.8.0_144 ./java8
#配置环境变量
ENV JAVA_HOME=$JAVA_DIR/java8
ENV PATH=$JAVA_HOME/bin
#入口,java项目的启动命令
ENTRYPOINT ["java", "-jar", "/tmp/app.jar"]
```
- 例子:从jdk镜像构建一个java项目
方法一: 直接把jar文件构拷贝到包中。 此方法适合发布不修改的jar项目。
```yml
#基础镜像
FROM openjdk:11.0-jre-buster
#设置时区,默认时区不是东八区
ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
#拷贝jar包
COPY docker-demo.jar /app.jar
#入口
ENTRYPOINT ["java", "-jar", "/app.jar"]
```
方法二:
- 首先构建一个openjdk镜像
```bash
#Dockerfile
#基础镜像
FROM openjdk:11.0-jre-buster
#设置时区,默认时区不是东八区
ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
```
- 用run构建容器
```bash
#run 后面可以直接跟执行命令,这样可以把jar文件映射进去,然后启动执行
sudo docker run -d --name app.jar -p 8080:8080 -v ./app:/app openjdk11:1.0 java -jar /app/app.jar
#更新jar包: 只需要stop容器,更新jar文件,start容器即可。
```
- 命令
- docker build -t myImage:1.0 .
- -t tag的缩写,后面是名称:tag . 在最后,指定dockerfile文件所在的目录 注意COPY中使用的路径都是相对这个路径的
- 建立好的镜像就在docker中,可以使用docker images 查看
- 配置文件名: Dockerfile
## 容器网络互联
- docker inspect 容器名
- 可以查看容器的ip地址,每个容器都有自己的ip地址
- 初始网络
- 安装docker的时候会在机器上安装一个虚拟网卡:名字 docker0 并创建一个虚拟的网桥:172.17.0.1/16 【16】前16位不能动
- 容器之间是可以互相连通的
- 容器的ip地址不是固定的,需要做自定义网络,可以通过容器名访问
- 不能使用IP地址链接,ip地址是会变的
- 同一网桥中的容器可以互相访问,不是同一网桥的不能互相访问。
- ⚠️:默认网络不能通过容器名称进行互相访问,ip地址可以,但IP地址是变化的不准确不能使用

- 自定义网桥
- 必须是自定义网络中才可以通过容器名称进行访问
- 默认网络是没有这个功能的
- 所以要做容器之间的网络通信,就必须要自定义网络

- 命令
- docker network create
- 创建一个网络
- 创建一个网络会在宿主机上多出一个虚拟网卡,增加一个网段,默认是网桥的模式
- docker network ls
- 查看所有网络
- docker network rm
- 删除指定网络
- docker network prune
- 删除未使用的网络
- docker network connect
- 使指定容器链接加入网络
- docker network connect 网络名字 容器名字
- 容器加入网络后,会同时在两个网络中
- docker network disconnect
- 使指定容器链接断开某网络
- docker network inspect
- 查看网络详细信息
- docker run --network 网络名称
- 创建的容器直接在这个网络中
## 项目的部署 「docker compose」
- docker-compose.yml
- version 可以设置 2.x 和 3.x 「这个是旧版了,version已经不需要设置了」
- version 现代docker compose不需要设置 「也就是 compose v2版本以上」
- docker compose 可以运行就是v2版本的compose,不需要设置version
- docker compose version 查看版本信息
- 模版

- docker run 和docker-compose.yml 语法之间的对比

entrypoint 定义容器启动时运行的主程序(可执行文件或脚本)。
command 作为参数传递给 entrypoint(相当于 ENTRYPOINT 的默认参数)。
```yaml
services:
webapp:
image: nginx:alpine
entrypoint: ["/run.sh"]
command: ["arg1", "arg2", "arg3"]
```
执行命令为: /run.sh arg1 arg2 arg3
> **关键点**
>
> 如果 entrypoint 是列表形式(如 ["/docker-entrypoint.sh"]):
>
> Docker 会直接执行 /docker-entrypoint.sh,并附加 command 作为参数。
>
> 不会 通过 shell 解析(如 sh -c),所以环境变量替换等 shell 功能不会自动生效。
>
> 如果 entrypoint 是字符串形式(如 "/docker-entrypoint.sh"):
>
> Docker 会通过 /bin/sh -c 执行,支持 shell 功能(如变量替换 $VAR)。
>
> 但推荐使用列表形式以避免 shell 解析的意外行为。
>
> 如果 entrypoint 未设置:
>
> 会使用镜像中定义的 ENTRYPOINT(来自 Dockerfile)。
>
> command 会完全覆盖 Dockerfile 的 CMD。
- 容器启动执行的命令用参数 command:进行配置
```yml
services:
app.jar:
image: openjdk11:1.0
container_name: app.jar
volumes:
- "./app:/app"
command: java -jar /app/app.jar
networks:
- net
networks:
net:
external: true #使用已经创建的网络
```
## 限制容器使用资源
在 Docker 中,可以通过多种方式限制容器使用的资源(CPU、内存、磁盘 I/O 等)。以下是常用的资源限制方法:
1. **内存限制**
限制容器最大内存使用量:
```bash
docker run -it --memory="1g" --memory-swap="2g" ubuntu
```
- `--memory`:容器可用的物理内存上限(例如 `1g` 表示 1GB)。
- `--memory-swap`:内存+交换分区的总限制(需 ≥ `--memory`)。
- `--memory-swappiness`:控制交换分区的使用比例(0-100,0 表示禁用交换)。
防止容器耗尽宿主机内存:
```bash
docker run -it --memory="500m" --oom-kill-disable ubuntu
```
- `--oom-kill-disable`:禁止 OOM Killer 终止容器进程(慎用)。
1. CPU 限制**
限制容器使用的 CPU 核心数:
```bash
docker run -it --cpus="1.5" ubuntu
```
- `--cpus`:限制容器最多使用 1.5 个 CPU 核心。
绑定到指定 CPU 核心:
```bash
docker run -it --cpuset-cpus="0,2" ubuntu
```
- `--cpuset-cpus`:限制容器只运行在 CPU 0 和 2 上。
按权重分配 CPU 时间:
```bash
docker run -it --cpu-shares="512" ubuntu
```
- `--cpu-shares`:默认值为 1024,权重越高分配的 CPU 时间越多(相对比例)。
1. 磁盘 I/O 限制
限制磁盘读写带宽:
```bash
docker run -it \
--device-read-bps="/dev/sda:1mb" \
--device-write-bps="/dev/sda:1mb" \
--device-read-iops="/dev/sda:100" \
--device-write-iops="/dev/sda:100" \
ubuntu
```
- `--device-read-bps`/`--device-write-bps`:限制每秒读写带宽(例如 `1mb`)。
- `--device-read-iops`/`--device-write-iops`:限制每秒 IO 操作次数。
1. 进程数限制(PID 限制)
```bash
docker run -it --pids-limit=100 ubuntu
```
- `--pids-limit`:限制容器内最大进程数(防止 fork 炸弹)。
1. 使用 `docker-compose` 配置资源限制**
在 `docker-compose.yml` 中示例:
```yaml
services:
app:
image: ubuntu
deploy:
resources:
limits:
cpus: "0.5"
memory: 500M
reservations:
memory: 200M
```
- `limits`:硬性限制。
- `reservations`:预留资源(仅 Swarm 模式下有效)。
1. 动态查看资源使用情况
```bash
docker stats [容器名]
```
实时监控容器的 CPU、内存、网络等资源占用。
1. **注意事项**
1. **资源限制的优先级**:部分参数(如 `--memory`)是硬限制,超出会导致容器被终止。
2. **Swarm/Kubernetes**:在生产环境中,通常结合编排工具(如 Swarm/K8s)实现更精细的资源管理。
3. **性能影响**:过度限制可能导致容器性能下降,需根据实际需求调整。
4. **建议**: 不限制容器资源,而是通过监控报警的方式进行管理。
## 多容器

depends_on 依赖哪个容器
- 配置文件和镜像生成
```yml
#docker-compose.yml
services:
ruoyi-mysql:
container_name: ruoyi-mysql
#设置了image映像得到过程如下:
#1. 从本地查找镜像是否存在,存在直接使用
#2. 从中央仓库查找镜像是否存在,存在下载
#3. 中央仓库没有,配置文件中有build,则从build指定的配置文件中创建。
#4. 如果没有build则找不到映像。
#没有设置image映像的得到过程:
#1. 通过build指定的dockerfile配置文件,生成镜像。
# 镜像名称一般是项目名称「执行docker compose时候指定的」-服务名称。
#建议:
#1. 非必要不要自己通过dockerfile建立映像,尽量使用run的参数「或者compose配置文件」去生成。
#2. 如果一定要创建映像文件,则尽量把image的名字起的不重复防止中央仓库中有而下载。
# 更好的办法是不指定image的名字,而是up的时候现生成一个映像。
# image: mysql:5.7
build:
context: .
dockerfile: mysql-dockerfile
ports:
- "3306:3306"
volumes:
- ./mysql/conf:/etc/mysql/conf.d
- ./mysql/logs:/logs
- ./mysql/data:/var/lib/mysql
command: [
'mysqld',
'--innodb-buffer-pool-size=80M',
'--character-set-server=utf8mb4',
'--collation-server=utf8mb4_unicode_ci',
'--default-time-zone=+8:00',
'--lower-case-table-names=1'
]
environment:
MYSQL_DATABASE: 'ry-vue'
MYSQL_ROOT_PASSWORD: password
```
- links、external-links、network的关系
`external_links` 和 `links` 都是用于在 Docker 中建立容器之间的链接关系,但它们在使用方式和适用范围上有一些区别。
1. 语法和使用方式:
- `links`:`links` 是 Docker Compose 中的字段,用于在同一 Compose 文件中定义容器之间的链接关系。它使用的语法是将容器名称指定为链接的目标,并可以为链接指定别名。例如:`links: - container1:alias1`。
- `external_links`:`external_links` 是 Docker Compose 中的字段,用于在容器之间建立链接关系,但链接的目标容器不一定在同一 Compose 文件中定义。它使用的语法是将外部容器的名称指定为链接的目标,并可以为链接指定别名。例如:`external_links: - container2:alias2`。
2. 适用范围:
- `links`:`links` 字段适用于同一 Docker Compose 文件中的容器之间的链接关系。它使得容器可以通过链接的别名来进行网络连接和服务访问。
- `external_links`:`external_links` 字段适用于在不同 Docker Compose 文件、甚至不同项目中的容器之间建立链接关系。它使得容器可以通过链接的别名来访问在其他 Compose 文件或项目中定义的容器服务。
3. 推荐使用:
- `links`:在较新的 Docker Compose 版本中,`links` 已经被弃用,不再推荐使用。取而代之的是使用自定义网络(networks)来定义容器之间的关联关系。
- `external_links`:虽然 `external_links` 仍然可用,但在较新的 Docker Compose 版本中,也推荐使用自定义网络(networks)来定义容器之间的链接关系,以提供更灵活和可控的网络连接方式。
总结来说,`links` 用于在同一 Compose 文件中定义容器之间的链接关系,而 `external_links` 用于在不同 Compose 文件或项目中的容器之间建立链接关系。然而,推荐使用自定义网络(networks)来取代 `links` 和 `external_links`,以提供更好的网络管理和连接方式。
## docker compose 命令

```bash
#up 一键启动
#down 一键删除
docker compose up -d #-d后台运行,-d 一定要放在up的后面
sudo docker compose down #容器、网络会被删除,下砸的影像不会被删除
```
- docker compose 多服务器部署
- 可以做单服务器多实例的负载均衡
- Docker Compose 本身不支持跨多个服务器分布式部署。如果你想要在多个服务器上运行容器,你需要在每台服务器上分别运行Docker和Docker Compose,并在每台服务器上定义相同的服务。
但是,你可以使用Docker Swarm或Kubernetes这样的编排工具来在多个服务器上部署容器,并且可以通过编排工具来管理这些容器的分布式部署。
## 备份
- 使用以下命令备份所有正在运行的容器及其卷
- 备份前停止所有的容器 docker stop $(docker ps -aq)
```sh
docker ps -a -q | xargs -I {} docker export {} -o container_{}.tar
docker volume ls -q | xargs -I {} docker run --rm -v {}:/data -v $(pwd):/backup ubuntu tar czf /backup/volume_{}.tar.gz /data
```
- docker export 是 Docker 的一个命令,用于将容器的文件系统导出为一个 tar 归档文件,但不包含容器的元数据、日志或运行状态信息。它主要用于持久化容器的文件系统快照,适用于数据备份或迁移场景。
```bash
#基本用法
docker export [OPTIONS] CONTAINER > output.tar
#或
docker export [OPTIONS] CONTAINER -o output.tar
#CONTAINER:可以是容器名称或 ID。
#output.tar 或 -o output.tar:将导出的内容保存为 .tar 文件。
```
与 docker save 的区别
- 
与 docker commit 的区别
- 
- 备份配置文件
```sh
#Linux 系统
sudo cp /etc/docker/daemon.json ~/docker_daemon_backup.json
```
- 备份 Docker 数据目录
```sh
#通常位于 /var/lib/docker
#可以使用 docker info 查看
sudo docker info |grep "Docker Root Dir"
sudo tar czf docker_data_backup.tar.gz /var/lib/docker
```