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/docker
    
  • mac
    • 在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:latest      
    
  • docker run 「创建并运行一个容器」
    #如果没有发现镜像,会下载一个镜像,然后运行容器
    docker run -d --name mysql -p 3306:3306 -e TZ=Asia/Shanghai -e MYSQL_ROOT_PASSWORD=123 mysql
    
    • -d : 容器后台运行;不加这个参数会卡住在控制台,停止后进程会停止
    • --name 指定容器的名称
    • -p 宿主机端口:容器内端口
    • 例如: -p 3307:3306
    • -e 环境变量,不同镜像的变量不同
    • mysql 是镜像的名字
    • 完整写法: mysql:5.7
    • tag不写就是 lastest
    • -v 宿主机目录:容器内部目录
    • 宿主机目录没有:自动创建
    • 容器内部目录没有:自动创建
    • 都没有:同时创建
    • -w
    • 指定容器内部的工作目录
  • docker stop 容器 「停止容器的运行,并没有删除容器」
  • docker start 容器 「启动 容器进程」
  • docker ps
    • 查看容器状态,默认只显示运行的容器 -a 查看所有容器
    • 已表格的方式查看
    docker ps --format "table {{.ID}}\t{{.Image}}\t{{.Ports}}\t{{.Status}}\t{{.Names}}"
    #可以做一个linux的命令别名
    dps='docker ps --format "table {{.ID}}\t{{.Image}}\t{{.Ports}}\t{{.Status}}\t{{.Names}}"'
    #简化显示
    docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Image}}\t{{.ID}}"
    
  • docker rm
    • 删除容器 容器中的数据会被删除
    • -f 强制删除容器,可以删除运行的容器
  • docker exec
    • 执行命令进入容器内步
    • -it 进入交互状态
      docker exec -it 容器名 bash
      #执行mysql 命令 带参数
      docker exec -it 容器名 mysql -uroot -p
      
  • docker save 「可以写多个image,这样就把多个镜像保存了」
docker save -o 输出文件名.tar  ngnix:latest
  • docker 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

清理镜像、容器、卷、网络

  • 清理 「镜像、容器、卷、网络的清理」
  • https://blog.51cto.com/u_16175493/8099417
  • 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」
      • ⚠️:数据卷不存在会自动创建,并会拷贝容器中的内容
      • 用途⚠️:可以使用没有的卷做映射,这样可以把容器里的数据和配置文件拿到
      #系统中没有nginx-html卷, 执行此命令后创建卷并且卷中有网页内容
      sudo docker run --name nginx -v nginx-html:/usr/share/nginx/html -d nginx:stable
      
  • docker inspect 容器名
    • 查看容器详情
  • 匿名卷
    • 不是我们创建的,容器创建的时候默认创建的卷叫匿名卷,名字是一长串。
    • mysql : 创建mysql容器的时候,会自动创建一个存储数据库数据的卷
  • 删除容器的时候数据卷不会被删除
    • 也就是说数据会被永久保留

本地目录挂载

  • docker run -v 本地目录:容器内目录
    • 与挂载数据卷方法相同,只是使用的本地目录
    • 目录必须使用路径开头,可以是绝对路径或相对路径。
    • 例如: -v mysql:/var/lib/mysql 这就是挂载一个数据卷 -v ./mysql:/var/lib/mysql 就是挂载本地目录
  • 步骤,查看映像官方文档,把所有需要的目录都挂载到本地。 alt text
  • mysql 挂载本地目录
    #本地的三个目录要提前创建好
    #配置文件和脚本,提前拷贝进去 , 配置文件可以通过提前安装一个myslq进行获取。
    docker run -d \
        --name mysql \
        -p 3306:3306 \
        -e TZ=Asia/Shanghai \
        -e MYSQL_ROOT_PASSWORD=123 \
        -v ./data:/var/lib/mysql \
        -v ./init:/docker-entrypoint-initdb.d \  #只在run的时候执行
        -v ./conf:/ect/mysql/conf.d \
        mysql
    #执行后data目录会有数据库的内容
    #run的时候把初始化数据库的脚本放到初始化目录里面。进行数据库的创建和基础数据的加入。
    

本地文件和文件夹挂载到容器的文件关系

背景介绍

docker volume 可以使我们在启动docker容器时,动态的挂载一些文件(如配置文件), 以覆盖镜像中原有的文件,但是,挂载一个主机上尚不存在的文件夹或者文件到容器中会怎样呢?这里特意做了一下实践,记录实验结果如下:

「文件夹挂载」

docker在文件夹挂载上的行为是统一的,具体表现为:

  • 若文件夹不存在,则先创建出文件夹(若为多层文件夹,则递归创建)
  • 用host上的文件夹内容覆盖container中的文件夹内容
docker run -v /path-to-folder/A:/path-to-folder/B test-image

详细说明如下:

host上文件夹存在,且非空

hostcontainermount result
存在的非空文件夹A不存在的文件夹B先在contanier中创建文件夹B,再将A文件夹中的所有文件copy到B中
存在的非空文件夹A存在的非空文件夹B先将container中文件夹B的原有内容清空,再将A中文件copy到B中

无论container中的文件夹B是否存在, A都会完全覆盖B的内容

host上文件夹存在,但为空

hostcontainermount result
存在的空文件夹A存在的非空文件夹Bcontainer中文件夹B的内容被清空

container中对应的文件夹内容被清空

host上文件夹不存在

hostcontainermount result
不存在的文件夹A存在的非空文件夹B在host上创建文件夹A,container中文件夹B的内容被清空
不存在的文件夹A/B/C存在的非空文件夹B在host上创建文件夹A/B/C,container中文件夹B的内容被清空

container中对应的文件夹内容被清空

总结

host上文件夹一定会覆盖container中文件夹:

hostcontainermount result
文件夹不存在/文件夹存在但为空文件夹不存在/存在但为空/存在且不为空container中文件被覆盖(清空)
文件夹存在且不为空文件夹不存在/存在但为空/存在且不为空container中文件夹内容被覆盖(原内容清空, 覆盖为host上文件夹内容)

「文件挂载」

文件挂载与文件夹挂载最大的不同点在于:

  • ⚠️:docker 禁止用主机上不存在的文件挂载到container中已经存在的文件
  • 文件挂载不会对同一文件夹下的其他文件产生任何影响

除此之外, 其覆盖行为与文件夹挂载一致,即:

  • 用host上的文件的内容覆盖container中的文件的内容
docker run -v /path-to-folder/non-existent-config.js:/path-to-folder/config.js test-image # forbidden

详细说明如下:

  • host上文件不存在
hostcontainermount result
不存在的文件configA.js已经存在的文件congfigB.js报错,Are you trying to mount a directory onto a file (or vice-versa)? Check if the specified host path exists and is the expected type. 同时会在host上生成两个空目录 configA.js 和 configB.js, 但是container无法启动
  • host上文件存在
hostcontainermount result
存在的文件configA.js存在的文件congfigB.jscontainer中文件名configB.js保持不变,但是文件内容被congfigA.js的内容覆盖了
存在的文件configA.js不存在的文件congfigB.jscontainer中新建一个文件configB.js,其内容为configA.js的文件内容, configB.js所在文件下的所有其他文件维持不变
  • 总结

host上文件一定会覆盖container中文件夹

hostcontainermount result
不存在的文件已经存在的文件禁止行为
存在的文件不存在的文件/已经存在的文件新增/覆盖 (若目录不存在则会创建目录)

结论

「文件夹挂载」

  • 允许不存在的文件夹或者存在的空文件夹挂载进container, container中对应的文件夹将被清空
  • 非空文件夹挂载进container将会覆盖container中原有文件夹

「文件挂载」

  • 禁止将不存在的文件挂载进container中已经存在的文件上
  • 存在的文件挂载进container中将会覆盖container中对应的文件, 若文件不存在则新建

应用场景

  1. 从上面的分析可知,文件夹挂载以整个文件夹为单位进行文件覆盖,故可在需要将大量文件挂载进container时使用,另外,如果挂载一个空文件夹或者不存在的文件夹,一般是做逆向使用: 即容器启动后,可能会在容器内挂载点的文件夹下生成一些文件(如日志),此时,在对应的host上的文件夹内就能直接看到。
  2. 文件挂载由于只会覆盖单个文件而不会影响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

制作自己的镜像 用途

⚠️:我们自己制作好的项目做成镜像需要以下内容:

  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
    • 指定维护者信息
    • 可以包括:姓名 邮箱等
      # 指定维护者信息
      MAINTAINER OceanXDevelopment <isupport@oceanxtech.com>
      
    • ADD
    • 该命令将复制指定的 路径下内容到镜像中的 路径下
    • ⚠️:ADD 和 COPY 的区别和使用场景
      • ADD 支持添加远程 url 和自动提取压缩格式的文件,COPY 只允许从本机中复制文件
      • COPY 支持从其他构建阶段中复制源文件(–from)
      • 根据官方 Dockerfile 最佳实践,除非真的需要从远程 url 添加文件或自动提取压缩文件才用 ADD,其他情况一律使用 COPY
      • ⚠️:ADD 从远程 url 获取文件和复制的效果并不理想,因为该文件会增加 Docker Image 最终的大小。相反,应该使用 curl huo wget 来获取远程文件,然后在不需要它时进行删除
    • VOLUME
    • 创建一个匿名数据卷挂载点
      VOLUME /home/ruoyi/redis
      
  • 官方详细文档
  • 例子:从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 run -d --name nginx -p 80:80 --network test
    

项目的部署 「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 等)。以下是常用的资源限制方法:

  1. 内存限制

限制容器最大内存使用量:

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 终止容器进程(慎用)。
  1. 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 时间越多(相对比例)。
  1. 磁盘 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 操作次数。
  1. 进程数限制(PID 限制)
docker run -it --pids-limit=100 ubuntu
  • --pids-limit:限制容器内最大进程数(防止 fork 炸弹)。
  1. 使用 docker-compose 配置资源限制** 在 docker-compose.yml 中示例:
services:
  app:
    image: ubuntu
    deploy:
      resources:
        limits:
          cpus: "0.5"
          memory: 500M
        reservations:
          memory: 200M
  • limits:硬性限制。
  • reservations:预留资源(仅 Swarm 模式下有效)。
  1. 动态查看资源使用情况
docker stats [容器名]

实时监控容器的 CPU、内存、网络等资源占用。

  1. 注意事项
    1. 资源限制的优先级:部分参数(如 --memory)是硬限制,超出会导致容器被终止。
    2. Swarm/Kubernetes:在生产环境中,通常结合编排工具(如 Swarm/K8s)实现更精细的资源管理。
    3. 性能影响:过度限制可能导致容器性能下降,需根据实际需求调整。
    4. 建议: 不限制容器资源,而是通过监控报警的方式进行管理。

多容器

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: password
  • links、external-links、network的关系

external_linkslinks 都是用于在 Docker 中建立容器之间的链接关系,但它们在使用方式和适用范围上有一些区别。

  1. 语法和使用方式:
    • linkslinks 是 Docker Compose 中的字段,用于在同一 Compose 文件中定义容器之间的链接关系。它使用的语法是将容器名称指定为链接的目标,并可以为链接指定别名。例如:links: - container1:alias1
    • external_linksexternal_links 是 Docker Compose 中的字段,用于在容器之间建立链接关系,但链接的目标容器不一定在同一 Compose 文件中定义。它使用的语法是将外部容器的名称指定为链接的目标,并可以为链接指定别名。例如:external_links: - container2:alias2
  2. 适用范围:
    • linkslinks 字段适用于同一 Docker Compose 文件中的容器之间的链接关系。它使得容器可以通过链接的别名来进行网络连接和服务访问。
    • external_linksexternal_links 字段适用于在不同 Docker Compose 文件、甚至不同项目中的容器之间建立链接关系。它使得容器可以通过链接的别名来访问在其他 Compose 文件或项目中定义的容器服务。
  3. 推荐使用:
    • links:在较新的 Docker Compose 版本中,links 已经被弃用,不再推荐使用。取而代之的是使用自定义网络(networks)来定义容器之间的关联关系。
    • external_links:虽然 external_links 仍然可用,但在较新的 Docker Compose 版本中,也推荐使用自定义网络(networks)来定义容器之间的链接关系,以提供更灵活和可控的网络连接方式。

总结来说,links 用于在同一 Compose 文件中定义容器之间的链接关系,而 external_links 用于在不同 Compose 文件或项目中的容器之间建立链接关系。然而,推荐使用自定义网络(networks)来取代 linksexternal_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 /data
    
    • docker 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 export容器仅当前文件系统快照(单层)备份或迁移容器数据
    docker save镜像整个镜像(包括历史和层结构)分发或存档镜像

    与 docker commit 的区别
    命令功能
    docker commit会将容器的变更保存为新镜像(保留元数据)。
    docker export仅生成一个无元数据的文件系统快照(不可直接运行)。
  • 备份配置文件
    #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