一、什么是Docker
Docker是一个开源的容器管理引擎,可以将应用程序直接打包到一个可移植的容器中,运行在任意支持Docker的环境上
- Docker的工作原理:使用操作系统级别的虚拟化技术实现容器的隔离和资源管理(可以简单理解成轻量化的虚拟机)与虚拟机相比,Docker更加轻量化,启动和停止速度更快,资源消耗更低,更容易管理和扩展
- Docker的核心特点
- 轻量化:Docker容易只包含应用程序和最基本的系统组件,容易部署、管理和扩展
- 可移植性:在所有支持Docker环境的服务器可以随意部署
- 灵活性:通过镜像打包应用程序和依赖项,无需重新编译就能在不同环境运行
- 可拓展性:支持动态增减容器,实现弹性扩展
- 安全性:Docker提供数据卷和其它安全特性,保护数据和应用程序免受攻击
- Docker应用场景
- 自动化部署:通过Docker自动化构建、部署应用程序
- 持续集成/持续部署(CI/CD):Docker支持自动化测试和CI/CD
- 微服务架构:Docker适合管理和构建微服务架构,每个服务可以独立部署和扩展
二、安装Docker
- Linux环境安装,以Centos为例,其它系统参考官方安装文档地址docs.docker.com/engine/inst…
# 1.移除旧版本docker
sudo yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
# 2.安装yum功能增强包
sudo yum install -y yum-utils
# 3.配置docker yum源地址
sudo yum-config-manager \
--add-repo \
http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# 4.安装docker和docker-compose
sudo yum install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
# 5.设置开机自启动
systemctl enable docker --now
# 6.配置docker加速镜像
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<EOF
{
"registry-mirrors": [
"https://docker.m.daocloud.io"
]
}
EOF
# 7.重新加载docker守护进程配置并重启dokcer
sudo systemctl daemon-reload
sudo systemctl restart docker
# 8.测试docker是否安装成功
docker -v
- Windows环境安装
- 下载Docker Desktop,下载地址docs.docker.com/desktop/set…
- 开启Hyper-V
左键单击电脑左下角开始按钮—>点击“设置”—>搜索“
Windows功能”—>启用或关闭Windows功能—>勾选Hyper-v,启用后电脑会重启,安装环境配置成功
{
"builder": {
"gc": {
"defaultKeepStorage": "20GB",
"enabled": true
}
},
"experimental": false,
"registry-mirrors": [
"https://docker.m.daocloud.io",
"https://docker.aityp.com",
"https://lispy.org"
]
}
- 测试是否安装成功,打开cmd窗口执行docker -v看看是否打印docker版本信息,有版本信息输出即安装成功
三、Docker常用命令
- 查看指定命令有哪些操作
# 查看docker所有指令帮助手册
docker --help
# 例子:查看pull指令帮助手册
docker pull --help
# 例子:查看compose帮助手册
docker compose --help
- 镜像相关操作
# 没有指定镜像版本信息,默认下载latest版本,也就是最新版本
docker pull nginx
# 下载指定版本镜像
docker pull nginx:1.26.0
# 查看已下载镜像列表
docker images
# 根据id删除指定镜像
docker rmi imgaeId
# 批量删除所有镜像
docker rmi $(docker images -q)
- 容器相关操作
# 查看运行中的容器
docker ps
# 查看所有容器,包含stop的镜像
docker ps -a
# 启动容器,nginx是镜像名称,没有指定版本默认是启动latest,如果镜像没下载会自动下载
docker run nginx
docker run nginx:v1.26.0
# 启动容器并给容器取名为mynginx,该名称可以方便停止或重启容器,以及自定义网络中与其它容器交互
docker run --name mynginx nginx:1.26.0
# 后台启动容器
docker run -d --name mynginx nginx:1.26.0
# 后台启动容器并暴露指定端口号,多个端口可以多个-p传参
docker run -d --name mynginx -p 8080:80 -p 8848:8848 nginx:1.26.0
# 停止容器
docker stop 容器名称/容器id
# 启动容器
docker start 容器名称/容器id
# 重启容器
docker restart 容器名称/容器id
# 查看容器资源占用情况
docker stats 容器名称/容器id
# 查看容器信息
docker inspect 容器名称/容器id
# 进入正在运行的容器
docker exec -it 容器名称/容器id /bin/bash
docker exec -it 容器名称/容器id /sh/bash
# 删除容器,删除之前需要stop容器
docker rm 容器名称/容器id
# 强制删除容器,不用stop容器
docker rm -f 容器名称/容器id
# 强制删除所有容器
docker rm -f $(docker ps -a -q)
# 如果容器有修改,想要持久化保存,可以打包容器成为一个新的镜像
docker commit -m "update xxxx" 容器名称/容器id 新镜像名称:新镜像版本
docker commit -m "update 配置文件" mynginx newnginx:v.10
# 保存镜像为指定文件
docker save -o mynginx.rar mynginx:v.10
# 将保存的文件加载成镜像
docker load -i mynginx.rar
4.docker目录挂载和卷映射
# 1.目录挂载,带有/,将主机的/app/html和容器的/usr/share/nginx/html目录进行关联挂载,
# 目录不存在时docker会自动创建,方便在主机直接修改或者查看容器内的文件,创建默认是空目录
# 例如:java服务日志、上传的文件进行目录挂载
-v /app/html:/usr/share/nginx/html
# 2.卷映射,没有/,将/var/lib/docker/volumes/mysql-data与容器的/mysql/data做映射关联,
# mysql-data卷不存在的时候docker会在/var/lib/docker/volumes目录下自动创建,
# 创建的时候默认会将容器内的文件复制到主机对应的卷目录
# 例子:初次创建的时候会把容器/mysql/data有数据会复制到主机指定的卷/var/lib/docker/volumes/mysql-data
# 例如:把mysql的配置目录卷映射到主机,这样就可以直接修改mysql相关配置
-v mysql-data:/mysql/data
# 后台启动一个name=mysql的容器,暴露的端口号是3306:3306,目录挂载/app/mysql-data:/var/lib/mysql,卷映射mysql:/etc/mysql
docker run -d --name mysql -p 3306:3306 -v /app/mysql-data:/var/lib/mysql -v mysql:/etc/mysql mysql:8.0.37-debian
- 卷相关命令
# 1.查看所有卷
docker volume ls
# 2.创建卷,docker将会在/var/lib/docker/volumes目录下创建卷名目录
docker volume create 卷名
# 2.删除指定卷
docker volume rm 卷名称
# 3.查看卷信息
docker volume inspect 卷名称
- 自定义网络相关命令
# 1.查看所有网络
docker network ls
# 2.创建网络
docker network create 网络名
# 3.删除指定网络
docker network rm 网络名
# 4.查看网络信息,可以查看同一个网络下的容器有哪些,同一个网络的容器可以直接使用容器名称作为host访问
docker network inspect 网络名
- java项目创建Dockerfile,然后根据Dockerfile文件创建对应镜像,以gateway服务为例
- Dockerfile文件内容,将该文件放在target同级目录,因为Dockerfile中声明jar文件地址是相对路径target/monkey-gateway-1.0-SNAPSHOT.jar
# 使用包含字体库的jdk8镜像
FROM frolvlad/alpine-java:jdk8-slim
# 设置工作目录为/app,目录不存在docker会自动创建。决定了后续 RUN、CMD、ENTRYPOINT、COPY 和 ADD 等指令的执行路径
WORKDIR /app
# 定义构建参数 JAR_FILE,默认值为 target/monkey-gateway-1.0-SNAPSHOT.jar
ARG JAR_FILE=target/monkey-gateway-1.0-SNAPSHOT.jar
# 将构建好的 JAR 文件复制到镜像中,并重命名为 app.jar
COPY ${JAR_FILE} app.jar
# 声明容器运行时监听的端口
EXPOSE 5700
# 设置环境变量,包括时区和 Java 运行时参数,用户启动可以覆盖掉环境变量
ENV TZ=Asia/Shanghai
ENV JAVA_OPTS="-Djava.security.egd=file:/dev/./urandom -Xms128m -Xmx256m"
ENV NACOS_HOST=127.0.0.1
ENV NACOS_PORT=8848
ENV NACOS_NAMESPACE=public
ENV NACOS_GROUP=DEFAULT_GROUP
ENV NACOS_USERNAME=nacos
ENV NACOS_PASSWORD=nacos
# 使用数组格式定义 CMD 指令,方便覆盖运行命令
CMD java $JAVA_OPTS -jar app.jar
- cd到target目录下,创建镜像gateway:1.0,注意命令最后面的.表示Dockerfile所在的目录为当前目录
docker build -t gateway:1.0 .
- 创建镜像成功后,将镜像推送到DockerHub或者私有镜像仓库,以推送DockerHUb为例,需要先创建DockerHub账号,具体百度
# 1.登陆DockerHub账号,按提示输入账号密码
docker login
# 2.给镜像打标签,一般带上DockerHub用户名,例如DockerHub用户名=monkey
docker tag gateway:1.0 monkey/gateway:1.0
# 3.推送镜像
docker push monkey/gateway:v1.0
- 编写docker-compose.yaml文件以及docker compose相关命令
- docker compose是用于定义和运行多个容器的Docker程序,通过编写yaml文件定义多个容器以及容器之间的关系,简化应用程序的部署和管理过程
- 通过docker run命令依次部署容器
#一、部署mysql,部署成功后创建nacos_config数据库,初始化nacos配置相关表
docker run -d --name mysql -p 3307:3306 -e MYSQL_ROOT_PASSWORD=123456 -e MYSQL_DATABASE=mk-cloud -v mysql-data:/var/lib/mysql -v mysql:/etc/mysql --restart always --network prod mysql:8.0.37-debian
#二、部署redis
docker run -d --name redis -p 6389:6379 -e REDIS_PASSWORD=123456 -v /app/redis/prodrd1:/bitnami/redis/data --restart always --network prod bitnami/redis
#三、部署nacos,设置数据库持久化,部署成功后访问nacos管理页面,导入项目配置文件,修改相关配置
docker run -d --name nacos -p 8848:8848 -p 9848:9848 -p 9849:9849 -p 7848:7848 -e MODE=standalone -v nacos:/home/nacos --restart always --network prod nacos/nacos-server:v2.5.1
#四、项目创建Dockerfile制造镜像,根据制造的镜像部署项目jar包
4.1.以gateway服务为例
根据Dockerfile的配置,需要cd到target同级别目录
#制造镜像,镜像后面的.表示在当前目录进行build,与Dockerfile中复制jar包的命令有关
docker build -t monkey-gateway:1.0 .
# windows启动测试制作的镜像是否正确
docker run -d --name gateway -p 5700:5700 -e NACOS_HOST=192.168.11.1 -e NACOS_PORT=8848 -e NACOS_NAMESPACE=dev -e NACOS_GROUP=mk -e NACOS_USERNAME=nacos -e NACOS_PASSWORD=nacos@2025 monkey-gateway:1.0
# 将制作的镜像保存为rar文件,方便上传服务器(也可将镜像直接上传DockerHub)
docker save -o gateway.rar monkey-gateway:1.0
# 上传服务器之后加载对应rar包得到镜像,在rar包路径下执行下面命令
docker load -i gateway.rar
# linux启动镜像命令,其中-v挂载了日志文件和上传文件目录
docker run -d --name gateway -p 5700:5700 -e NACOS_HOST=nacos -e NACOS_PORT=8848 -e NACOS_NAMESPACE=dev -e NACOS_GROUP=mk -e NACOS_USERNAME=nacos -e NACOS_PASSWORD=nacos@2025 -v /www/logs:/www/logs -v /www/upload:/www/upload --restart always --network prod monkey-gateway:1.0
4.2.以service-user-server服务为例
根据Dockerfile的配置,需要cd到target同级别目录
# 制造镜像,镜像后面的.表示在当前目录进行build,与Dockerfile中复制jar包的命令有关
docker build -t monkey-user-server:1.0 .
# windows启动测试制作的镜像是否正确
docker run -d --name user-server -p 5800:5800 -e NACOS_HOST=192.168.11.1 -e NACOS_PORT=8848 -e NACOS_NAMESPACE=dev -e NACOS_GROUP=mk -e NACOS_USERNAME=nacos -e NACOS_PASSWORD=nacos@2025 monkey-user-server:1.0
# 将制作的镜像保存为rar文件,方便上传服务器(也可将镜像直接上传DockerHub)
docker save -o user-server.rar monkey-user-server:1.0
# 上传服务器之后加载对应rar包得到镜像,在rar包路径下执行下面命令
docker load -i user-server.rar
# linux启动镜像命令,其中-v挂载了日志文件和上传文件目录
docker run -d --name user-server -p 5800:5800 -e NACOS_HOST=nacos -e NACOS_PORT=8848 -e NACOS_NAMESPACE=dev -e NACOS_GROUP=mk -e NACOS_USERNAME=nacos -e NACOS_PASSWORD=nacos@2025 -v /www/logs:/www/logs -v /www/upload:/www/upload --restart always --network prod monkey-user-server:1.0
- 将上面docker run的所有命令转成通过编写yaml文件定义容器和容器之间的关系
#设置项目名称,不设置docker会自动创建一个项目名称
name: mk
#设置项目服务
services:
# mysql容器,名称随意定义,在当前文件不要重复即可
mysql:
# 容器名称
container_name: mysql
# 容器镜像
image: mysql:8.0.37-debian
# 暴露端口,多个端口依次增加-即可
ports:
- 3307:3306
# 定义环境变量
environment:
- MYSQL_ROOT_PASSWORD=123456
- MYSQL_DATABASE=mk-cloud
#解决mysql启动报错mbind: Operation not permitted,允许容器中的进程修改其优先级
cap_add:
- SYS_NICE
# 定义容器挂载的目录和映射的卷,映射的卷需要在顶级元素volumes下面额外定义
volumes:
- mysql-data:/var/lib/mysql
- mysql:/etc/mysql
- /app/mysql/initsql/nacos-init.sql:/docker-entrypoint-initdb.d/nacos-init.sql
# 是否自动重启
restart: always
# 定义加入的网络,网络需要在顶级元素networks下面额外定义,同一个网络的容器可以直接使用容器名称作为host访问
networks:
- prod
# redis容器,名称随意定义,在当前文件不要重复即可
redis:
# 容器名称
container_name: redis
# 容器镜像
image: bitnami/redis
# 暴露端口,多个端口依次增加-即可
ports:
- 6389:6379
# 定义环境变量
environment:
- REDIS_PASSWORD=123456
# 定义容器挂载的目录和映射的卷,映射的卷需要在顶级元素volumes下面额外定义
volumes:
- /app/redis/prodrd1:/bitnami/redis/data
# 是否自动重启
restart: always
# 定义加入的网络,网络需要在顶级元素networks下面额外定义,同一个网络的容器可以直接使用容器名称作为host访问
networks:
- prod
# nacos容器,名称随意定义,在当前文件不要重复即可
nacos:
# 容器名称
container_name: nacos
# 容器镜像
image: nacos/nacos-server:v2.5.1
# 暴露端口,多个端口依次增加-即可
ports:
- 8848:8848
- 9848:9848
- 9849:9849
- 7848:7848
# 定义环境变量
environment:
- MODE=standalone
# 定义容器挂载的目录和映射的卷,映射的卷需要在顶级元素volumes下面额外定义
volumes:
- nacos:/home/nacos
# 是否自动重启
restart: always
# 定义加入的网络,网络需要在顶级元素networks下面额外定义,同一个网络的容器可以直接使用容器名称作为host访问
networks:
- prod
# 容器依赖关系,按照配置的先后顺序,当前容器会在依赖的容器启动后再启动
depends_on:
- mysql
# java服务gateway容器,名称随意定义,在当前文件不要重复即可
gateway:
# 容器名称
container_name: gateway
# 容器镜像
image: monkey-gateway:1.0
# 暴露端口,多个端口依次增加-即可
ports:
- 5700:5700
# 定义环境变量
environment:
- NACOS_HOST=nacos
- NACOS_PORT=8848
- NACOS_NAMESPACE=dev
- NACOS_GROUP=mk
- NACOS_USERNAME=nacos
- NACOS_PASSWORD=nacos@2025
# 定义容器挂载的目录和映射的卷,映射的卷需要在顶级元素volumes下面额外定义
volumes:
- /www/logs:/www/logs
- /www/upload:/www/upload
# 是否自动重启
restart: always
# 定义加入的网络,网络需要在顶级元素networks下面额外定义,同一个网络的容器可以直接使用容器名称作为host访问
networks:
- prod
# 容器依赖关系,按照配置的先后顺序,当前容器会在依赖的容器启动后再启动
depends_on:
- mysql
- redis
- nacos
# java服务user-server容器,名称随意定义,在当前文件不要重复即可
user-server:
# 容器名称
container_name: user-server
# 容器镜像
image: monkey-user-server:1.0
# 暴露端口,多个端口依次增加-即可
ports:
- 5800:5800
# 定义环境变量
environment:
- NACOS_HOST=nacos
- NACOS_PORT=8848
- NACOS_NAMESPACE=dev
- NACOS_GROUP=mk
- NACOS_USERNAME=nacos
- NACOS_PASSWORD=nacos@2025
# 定义容器挂载的目录和映射的卷,映射的卷需要在顶级元素volumes下面额外定义
volumes:
- /www/logs:/www/logs
- /www/upload:/www/upload
# 是否自动重启
restart: always
# 定义加入的网络,网络需要在顶级元素networks下面额外定义,同一个网络的容器可以直接使用容器名称作为host访问
networks:
- prod
# 容器依赖关系,按照配置的先后顺序,当前容器会在依赖的容器启动后再启动
depends_on:
- mysql
- redis
- nacos
#设置项目网络,docker会根据配置创建相关网络
networks:
prod:
#设置网络实际名称,不设置会按照项目名称_网络名称(mk_prod)
name: prod
#网络存在的时候使用已存在的网络,否则新创建
external: true
#设置项目卷映射,docker会更具配置创建相关卷,目录挂载不需要配置
volumes:
mysql-data:
#设置卷实际名称,不设置会按照项目名称_卷名(mk_mysql-data)
name: mysql-data
#卷存在的时候使用已存在的卷,否则新创建
external: true
mysql:
#设置卷实际名称,不设置会按照项目名称_卷名(mk_mysql)
name: mysql
#卷存在的时候使用已存在的卷,否则新创建
external: true
nacos:
#设置卷实际名称,不设置会按照项目名称_卷名(mk_nacos)
name: nacos
#卷存在的时候使用已存在的卷,否则新创建
external: true
- docker compose常用命令
# 1.按照compose.yaml依次后台启动容器,没有指定yaml文件的情况docker默认以当前目录下compose.yaml启动
docker compose up -d
# 2.指定yaml文件依次后台启动容器
docker compsoe -f my-compose.yaml up -d
# 3.根据指定yaml文件删除容器、网络,默认不删除卷
docker compose -f my-compose.yaml down
# 4.根据指定yaml文件删除容器、网络,删除卷
docker compose -f my-compose.yaml down -v
# 5.停止指定compose文件启动的所有容器,没有指定默认按照compose.yaml
docker compose -f my-compose.yaml stop
# 6.启动指定compose文件启动的所有容器,没有指定默认按照compose.yaml,该命令不能用于第一次启动,只能用于docker compose stop停止的
docker compose -f my-compose.yaml start
四、Docker镜像的分层机制
- 镜像层空间共享:相同镜像启动的不同容器共享同一个镜像的存储空间,镜像层是只读的
- 容器层空间独立:每个容器都有自己独立的容器层空间,对容器的修改实际就是修改容器层,因此不同容器之间是独立