
Docker 学习笔记
一、快速开始
以快速启动一个 MySQL 的 Docker 容器为例:
docker run -d \
--name mysql \
-p 3306:3306 \
-e TZ=Asia/Shanghai \
-e MYSQL_ROOT_PASSWORD=123 \
mysql命令解读:
docker run -d # 创建并运行一个容器,-d则是让容器以后台进程运行
--name mysqlname # 给容器起个名字叫 mysqlname
-p 3306:3306 # 端口映射,格式为: -p 宿主机端口:容器内端口
-e TZ=Asia/Shanghai # 配置容器运行时的参数
# 格式:-e KEY=VALUE,KEY和VALUE都由容器内进程决定
# 需要查看镜像文档来确定KEY和VALUE
mysql # 设置镜像名称,Docker会根据这个名字搜索并下载镜像1️⃣ Linux下输入如下命令
curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun
# 若安装失败,请检查 yum 源是否正常
systemctl start docker # 启动服务
systemctl enable docker # 开机自启2️⃣ 查看版本以验证是否正确运行
docker version三、Docker Images
Docker Images 类似于虚拟机镜像,是存放在 docker 仓库(Registry)的文件,是用于创建 docker 容器的模板。
3.1 镜像加速
国内从 DockerHub 拉取镜像有时会遇到困难,此时可以配置镜像加速器。Docker 官方和国内很多云服务商都提供了国内加速器服务,例如:
| 云服务商 | 地址 |
| 阿里云 | https://<你的ID>.mirror.aliyuncs.com |
在 /etc/docker/daemon.json 中写入如下内容(如果文件不存在请新建该文件)
{"registry-mirrors": ["镜像站网址"] } // 可以看到这里是一个list设置完之后需要重启 docker 服务
sudo systemctl daemon-reload
sudo systemctl restart docker3.2 获取镜像
docker pull REPOSITORY:TAG # 获取指定版本的镜像如果没加TAG,则默认拉取latest版本
3.3 镜像操作
1️⃣ 查看镜像信息
docker inspect 镜像名2️⃣ 搜索镜像
docker search centos # 以搜索centos镜像为例3️⃣ 删除镜像
docker rmi <镜像名>4️⃣ 导入或导出镜像
① save命令
docker save -o nginx.tar nginx:latest # "-o"也可用">"替代
# -o 和 > 表示输出到文件,nginx.tar为目标文件名,nginx:latest是源镜像② load命令
docker load -i nginx.tar # "-i"也可用"<"替代
# -i 和 < 表示从文件输入。会导入镜像及相关元数据,包括tag信息四、容器操作
1️⃣ 运行容器,并且将主机的8080端口映射到容器的80端口上
docker run -d --name=nginx -p 8080:80 nginx
# -d 指定容器在后台运行
# --name 指定容器名2️⃣ 进入容器交互
通过指定 -it 参数来保持标准输入打开,并且分配一个伪终端,是通过exec命令对容器执行操作时最为推荐的方式。使用docker exec --help 查看详细参数用法。
docker exec -it ContainerID /bin/bash # 或者去掉"/bin/"注:ContainerID 使用 docker ps -a 来查询
3️⃣ 容器常用操作
docker ps -a # 先查看在运行的容器,记下CONTAINER ID
docker rm -f <容器id> # 删除指定容器
docker stop <容器id> # 停止指定容器
docker start <容器id> # 启动指定容器
docker restart <容器id> # 重新启动容器
docker logs <容器id> # 重新启动容器
# 注:容器id可以只取前三位🚮 容器退出后自动删除:
docker run -it --rm nginx bash
# --rm 参数和 -d 参数不能同时使用五、数据挂载
5.1 数据卷(volume)挂载
数据卷是一个虚拟目录,是容器内目录与宿主机目录之间映射的桥梁
docker run -d --name nginx -p 80:80 -v html:/usr/share/nginx/html nginx
# -v 创建html数据卷,并映射到/usr/share/nginx/html
docker volume ls # 查看所有数据卷
# 结果:
DRIVER VOLUME NAME
local 29524ff09715d3688eae3f99803a2796558dbd00ca584a25a4bbc193ca82459f
local html
docker volume inspect html # 查看数据卷详情
# 结果
[
{
"CreatedAt": "2024-05-17T19:57:08+08:00",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/html/_data",
"Name": "html",
"Options": null,
"Scope": "local"
}
]
# 查看/var/lib/docker/volumes/html/_data目录
ll /var/lib/docker/volumes/html/_data # 等价于 ls -l,表示以长格式(-l)列出
# 进入该目录,并随意修改index.html内容
cd /var/lib/docker/volumes/html/_data
vi index.html出于容器内程序的存储需要,启动容器时未分配数据卷的容器,docker会自动为其创建一个“匿名数据卷”。演示一下查看MySQL的匿名数据卷:
# 查看MySQL容器详细信息
docker inspect mysql
# 关注其中.Config.Volumes部分和.Mounts部分5.2 本地目录挂载
这是更加推荐的方式
# 挂载本地目录
-v 本地目录:容器内目录
# 挂载本地文件
-v 本地文件:容器内文件容器内的目录是啥呢🧐?请参考 DockerHub:mysql - Official Image | Docker Hub
区别于5.1的volume挂载,本地目录或文件必须以 / 或 ./开头,如果直接以名字开头,会被识别为数据卷名而非本地目录名。
命令 | 说明 | 文档地址 |
|---|---|---|
docker volume create | 创建数据卷 | |
docker volume ls | 查看所有数据卷 | |
docker volume rm | 删除指定数据卷 | |
docker volume inspect | 查看某个数据卷的详情 | |
docker volume prune | 清除数据卷 |
六、制作镜像 —— Dockerfile
Dockerfile 是一个没有后缀名的文本文件,其中包含了一个个指令,声明了构建目标镜像需要的步骤。常见的指令如下:
指令 | 说明 | 示例 |
|---|---|---|
FROM | 指定基础镜像 | FROM centos:6 |
ENV | 设置环境变量,可在后面指令使用 | ENV key value |
COPY | 拷贝本地文件到镜像的指定目录 | COPY ./xx.jar /tmp/app.jar |
RUN | 执行Linux的shell命令,一般是安装过程的命令 | RUN yum install gcc |
EXPOSE | 指定容器运行时监听的端口,是给镜像使用者看的 | EXPOSE 8080 |
CMD | 容器启动时的默认命令(可被覆盖) | CMD ["python", "app.py"] |
ENTRYPOINT | 镜像中应用的启动命令,容器运行时调用 | ENTRYPOINT ["echo", "Hi"] |
部署 Java 应用的简单示例:
# 使用官方 OpenJDK 17 基础镜像(轻量级)
FROM openjdk:17-jdk-alpine
# 设置工作目录
WORKDIR /app
# 将本地的 JAR 包复制到容器中
COPY target/my-spring-boot-app.jar app.jar
# 暴露应用监听的端口(如 Spring Boot 默认的 8080)
EXPOSE 8080
# 定义容器启动时执行的命令
ENTRYPOINT ["java", "-jar", "/app/app.jar"]另一个 Dockerfile 示例:
# 指定基础镜像
FROM centos:7
# 维护者信息
MAINTAINER Cao Huan <huan_@outlook.com>
# 使用yum安装php
RUN yum install php-cli php-process php-devel php-pear libevent-devel -y
# 将当前目录下的BrowserQuest.tar.gz文件复制到镜像/root/web/文件夹下
COPY BrowserQuest.tar.gz /root/web/
# 修改镜像工作路径为/root/web/
WORKDIR /root/web/
# 解压当前工作路径下的 BrowserQuest.tar.gz 文件
RUN tar xzvf BrowserQuest.tar.gz
# 定义构建参数(可在构建时通过 --build-arg 指定)
ARG HOST_IP=localhost
# 生成 setup.sh 脚本,使用双引号允许变量替换,并转义内部的双引号
RUN echo -e "sed -i 's/hostip/$HOST_IP/g' Web/config/config_local.json && \
php start.php start" > BrowserQuest/setup.sh
# 添加可执行权限
RUN chmod +x BrowserQuest/setup.sh
# 修改镜像工作路径为 /root/web/BrowserQuest
WORKDIR /root/web/BrowserQuest
# 创建Docker容器创建时执行的命令,即修改hostip并启动游戏服
CMD ["bash","setup.sh"]
# 声明镜像内服务监听的端口
EXPOSE 8000 8787使用案例:上传 Gitee 代码,Jenkins 自动执行脚本,使用docker构建并部署应用
Jenkins 完成构建后执行的脚本:
#!/bin/bash
echo "开始制作镜像文件"
# 切换到项目根目录
cd /home/cat-community/
# 构建 Docker 镜像
docker build -t cat-community:latest .
# 暂停原服务
docker stop cat-community || true
# 删除原服务容器
docker rm cat-community || true
# 启动新服务(通过环境变量传递 JVM 参数)
# java ... 是容器启动时执行的具体命令
# > console.log: 将容器启动日志输出到 console.log 文件(覆盖模式)
docker run \
--name cat-community \
-p 8080:8080 \
-e JAVA_OPTS="-Xms512m -Xmx768m" \
-d \
cat-community
# 捕获容器日志
docker logs -f cat-community > console.log &
echo "部署完成"Jenkins 自动部署使用的 Dockerfile:
# 使用官方 OpenJDK 17 基础镜像
FROM openjdk:17
# 设置时区为上海
RUN /bin/cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
echo 'Asia/Shanghai' > /etc/timezone
# 复制 JAR 包
COPY cat-community-0.0.1.jar /home/cat-community/cat-community-0.0.1.jar
# 定义 JVM 参数环境变量(默认为空)
ENV JAVA_OPTS=""
# 暴露端口
EXPOSE 8080
# 启动命令:使用 sh -c 支持环境变量替换,是 shell 的语法而非 docker 的
CMD ["sh", "-c", "java $JAVA_OPTS -jar /home/cat-community/cat-community-0.0.1.jar --server.port=8080"]# ============ 仅使用 CMD 示例 ============
# Dockerfile: CMD 示例
CMD ["echo", "Hello from CMD"]
# 构建镜像:
# docker build -t cmd-example .
# 运行容器 (默认):
# docker run cmd-example
# 输出:
# Hello from CMD
# 覆盖 CMD:
# docker run cmd-example echo "Overridden CMD"
# 输出:
# Overridden CMD
# ============ 仅使用 ENTRYPOINT 示例 ============
# Dockerfile: ENTRYPOINT 示例
ENTRYPOINT ["echo", "Hello from ENTRYPOINT"]
# 构建镜像:
# docker build -t entrypoint-example .
# 运行容器 (默认):
# docker run entrypoint-example
# 输出:
# Hello from ENTRYPOINT
# 覆盖 ENTRYPOINT:
# docker run --entrypoint "/bin/sh" entrypoint-example -c "echo Overridden ENTRYPOINT"
# 输出:
# Overridden ENTRYPOINT
# ============ ENTRYPOINT + CMD 示例 ============
# Dockerfile: ENTRYPOINT + CMD 示例
ENTRYPOINT ["echo", "Hello"]
CMD ["from CMD"]
# 构建镜像:
# docker build -t combined-example .
# 运行容器 (默认):
# docker run combined-example
# 输出:
# Hello from CMD
# 覆盖 CMD 参数:
# docker run combined-example "Custom CMD"
# 输出:
# Hello Custom CMD七、容器间网络
要想实现容器之间的网络互联,可以通过docker为每个容器分配的默认网段(使用docker的默认网卡),也可以用docker新建网络(网桥),用于特定的一批需要互联的容器。
7.1 Docker 默认网络通信
# 查看某个容器的默认IP:
# 用基本命令,寻找Networks.bridge.IPAddress属性
docker inspect mysql
# 得到IP如下:172.17.0.2,该IP属于docker0网卡(ip addr 命令查看)此处得到的IP可以用于容器之间直接通信。进入另一个容器执行
docker exec -it <另一个容器id> bash # 进入另一个容器
ping 172.17.0.2 # 是可以 ping 通的7.2 自定义网络
# 1、创建网络
docker network create <网络名>
# 2、查看网络
docker network ls
# 3、让某些容器,都加入该网络,加入网络时可以通过 --alias 给容器起别名
# 别名可以用于该网络内的其它容器互相访问
docker network connect <网络名> <容器名> --alias <别名>
# 4、同样可以进入容器内 ping 测试【同一网络内容器】的连通性
docker exec -it <容器id> bash
ping <容器名> 或 <别名>八、Docker Compose
8.1 语法对比案例
用docker run部署MySQL的命令如下:
docker run -d \
--name mysql \
-p 3306:3306 \
-e TZ=Asia/Shanghai \
-e MYSQL_ROOT_PASSWORD=123 \
-v ./mysql/data:/var/lib/mysql \
-v ./mysql/conf:/etc/mysql/conf.d \
-v ./mysql/init:/docker-entrypoint-initdb.d \
--network hmall
mysql如果用docker-compose.yml文件来定义,就是这样:
version: "3.8"
services:
mysql:
image: mysql
container_name: mysql
ports:
- "3306:3306"
environment:
TZ: Asia/Shanghai
MYSQL_ROOT_PASSWORD: 123
volumes:
- "./mysql/conf:/etc/mysql/conf.d"
- "./mysql/data:/var/lib/mysql"
networks:
- new
networks:
new:
name: hmall8.2 完整案例
version: "3.8"
services:
mysql:
image: mysql
container_name: mysql
ports:
- "3306:3306"
environment:
TZ: Asia/Shanghai
MYSQL_ROOT_PASSWORD: 123
volumes:
- "./mysql/conf:/etc/mysql/conf.d"
- "./mysql/data:/var/lib/mysql"
- "./mysql/init:/docker-entrypoint-initdb.d"
networks:
- hm-net
hmall:
build:
context: .
dockerfile: Dockerfile
container_name: hmall
ports:
- "8080:8080"
networks:
- hm-net
depends_on:
- mysql
nginx:
image: nginx
container_name: nginx
ports:
- "18080:18080"
- "18081:18081"
volumes:
- "./nginx/nginx.conf:/etc/nginx/nginx.conf"
- "./nginx/html:/usr/share/nginx/html"
depends_on:
- hmall
networks:
- hm-net
networks:
hm-net:
name: hmall8.3 常见命令
# 启动所有, -d 参数是后台启动
docker compose up -d类型 | 参数或指令 | 说明 |
|---|---|---|
Options | -f | 指定compose文件的路径和名称 |
-p | 指定project名称。project就是当前compose文件中设置的多个service的集合,是逻辑概念 | |
Commands | up | 创建并启动所有service容器 |
down | 停止并移除所有容器、网络 | |
ps | 列出所有启动的容器 | |
logs | 查看指定容器的日志 | |
stop | 停止容器 | |
start | 启动容器 | |
restart | 重启容器 | |
top | 查看运行的进程 | |
exec | 在指定的运行中容器中执行命令 |
九、常见命令

命令 | 说明 | 文档地址 |
|---|---|---|
docker pull | 拉取镜像 | |
docker push | 推送镜像到DockerRegistry | |
docker images | 查看本地镜像 | |
docker rmi | 删除本地镜像 | |
docker run | 创建并运行容器(不能重复创建) | |
docker stop | 停止指定容器 | |
docker start | 启动指定容器 | |
docker restart | 重新启动容器 | |
docker rm | 删除指定容器 | |
docker ps | 查看容器 | |
docker logs | 查看容器运行日志 | |
docker exec | 进入容器 | |
docker save | 保存镜像到本地压缩文件 | |
docker load | 加载本地压缩文件到镜像 | |
docker inspect | 查看容器详细信息 |
