Docker入门到精通:容器化实战指南
一、Docker是什么?
Docker 是一个开源的应用容器引擎,用于开发、发布和运行应用程序。通过一种称为“容器化”的技术,将应用程序及其所有依赖项(如库、框架、运行时环境等)打包在一个标准化的单元中,这个单元就叫做容器。
二、容器与虚拟机的区别?
1、启动速度:每个虚拟都机是一个完整的操作系统包括操作系统和内核,所以它是一个重量级的系统。而容器是轻量级的,因为容器只打包了操作系统的基础文件和库文件、还有应用程序及所有的依赖,他的运行速度就如同在系统中创建一个进程一样快,所以启动速度较快。
2、运行性能:由于虚拟机增加了虚拟化层用于虚拟化硬件,势必会增加一定的开销,所以运行性能有所损失。而容器是直接运行在物理操作系统上的,他本身与系统上其他进程并没有太大区别,所以运行性能是接近原生的。
3、磁盘占用:虚拟机是一个完整的操作系统,是 GB 级别的,而容器只包含了一些系统启动的必要组件和程序依赖,是 MB 级别的。
4、数量:运行一个操作系统的开销较大,运行一个进程的开销较小,同样的服务器资源可以运行更多的容器。
5、隔离性:虚拟机是一个完整的操作系统级别的隔离,要比容器好很多;容器是进程级别的隔离,隔离的不彻底,因为多个容器之间使用的是同一个宿主机的操作系统内核。
6、封装速度:虚拟机封装会包含操作系统,封装速度比较慢,容器只封装操作系统的基础文件和库文件、应用程序、依赖,封装速度较快。
三、Centos安装Docker
1、安装Docker
# 添加 Docker 阿里云镜像源
sudo yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# 安装 Docker
sudo yum install -y docker-ce docker-ce-cli containerd.io
# 安装依赖包
sudo yum install -y yum-utils device-mapper-persistent-data lvm2
# 安装 Docker CE(社区版)
sudo yum install -y docker-ce docker-ce-cli containerd.io
2、启动Docker,并设置开机自启动
# 启动 Docker
sudo systemctl start docker
# 设置开机自启
sudo systemctl enable docker
# 检查 Docker 状态
sudo systemctl status docker
3、设置Docker的远程镜像源
tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://xget.xi-xu.me/cr/ghcr"]
}
目前,自从很多镜像源仓库关掉了对外服务,很多还能用的镜像源,速度都很慢,唯有https://xget.xi-xu.me/cr/ghcr这个镜像源挺快的。不过要设置成这个镜像源 ,Docker的版本要高一些才行,我这里的版本是26.1.4。我以前的Docker24,设置这个镜像源会出现daemon.json语法错误,因为这个版本只能设置域名,不能带/cr/ghcr路径。
四、Docker基本命令解析
1、拉取镜像
docker pull nginx:latest
- nginx #是镜像名
- :latest #指定要拉取镜像的版本,不写默认拉latest版本,也就是最新版本。
2、查看本地镜像
docker images
3、启动容器
docker run -d --name nginx -p 8080:80 -v /data/nginx:/opt/nginx/html nginx
- docker run #创建并启动容器命令,必写。
- -d #启动的容器后台运行的意思,非必写。
- –name #指定容器的名称,非必写。
- -p #指定映射宿主机和容器的端口,宿主机端口:容器的端口,非必写。
- -v #配置数据卷/目录挂载,实现数据持久化和初始化。把宿主机的配置文件映射到容器里面,又或者把容器里面生成的文件存储到宿主机上来。宿主机的目录:容器应用程序的目录。
- 最后的nginx,是镜像名称,你要创建并启动什么容器,就写什么容器的名称。
4、查看运行中的容器信息
docker ps
5、进入容器
docker exec -it nginx bash
- -it #打开终端交互(进入容器操作)
- nginx #容器名称
- bash #执行容器使用的 shell, bash 或 sh。
6、退出容器
exit
7、删除容器
rm- f nginx
8、删除容器镜像
#根据镜像名+版本删除
docker rmi nginx:latest
#根据镜像的IMAGE ID删除,二选一即可
docker rmi 41f689c20910
9、常用的容器日志命令
# 查看容器全部日志(从启动开始)
docker logs <容器ID或名称>
# 查看最后N行日志
docker logs --tail=100 <容器ID或名称> # 最后100行
# 实时跟踪日志(类似tail -f)
docker logs -f <容器ID或名称>
# 组合使用:实时查看最后100行
docker logs --tail=100 -f <容器ID或名称>
# 查看最近10分钟的日志
docker logs --since 10m <容器ID或名称>
# 查看指定时间之后的日志
docker logs --since "2023-09-10T12:00:00" <容器ID或名称>
# 查看某个时间段的日志
docker logs --since "2023-09-10T12:00:00" --until "2023-09-10T13:00:00" <容器ID或名称>
# 只显示最新日志(不输出历史)
docker logs --since 0s <容器ID或名称>
五、构建自定义镜像
1、构建命令
# 在 dockerfile 同目录下执行命令
docker build -t nginx:1.0.0 .
- -t #构建镜像的名称。
- . #表示 dockerfile 文件在当前目录下
2、自定义Dockerfile
FROM registry.cn-hangzhou.aliyuncs.com/jnzhyw/anapsi-alpine-java:8_server-jre_unlimited
MAINTAINER programname
RUN mkdir -p /programname/servicename/logs \
/programname/servicename/temp
WORKDIR /programname/servicename
ENV LANG=C.UTF-8 LC_ALL=C.UTF-8
ADD ./target/programname-servicename.jar ./app.jar
ADD ./target/classes/application-prod.yml ./application-prod.yml
ADD ./target/classes/application-dev.yml ./application-dev.yml
ADD ./target/classes/bootstrap-prod.yml ./bootstrap-prod.yml
ADD ./target/classes/bootstrap-dev.yml ./bootstrap-dev.yml
ENV spring.profiles.active="prod"
ENTRYPOINT ["java", "-jar", "app.jar"]
#CMD CMD ["echo", "Hello"]
- FROM #构建镜像需要一个基础镜像,centos:7.9.2009 就是一个基础镜像
- MAINTAINER #声明镜像维护者信息,标明镜像作者是 jnyw(已弃用语法,现在 推荐使用 LABEL)
- RUN mkdir -p #RUN 在基础镜像上要执行的命令。mkdir 创建目录结构,-p参数确保父目录不存在时自动创建。
- WORKDIR #设置工作目录,后续命令(如 ADD, RUN等)默认在此目录下执行,容器启动后也会自动进入此目录。
- ENV #设置环境变量。Spring Boot会自动将环境变量智能覆盖到应用配置中,所以可以达到Java的-Dproperties=true启动参数类似的效果,但不完全等效,而且-D优先级更高。
- ADD #将宿主机目录的文件拷贝到容器中并自动解压,宿主机的文件与 dockerfile 位于相同目录中
- CMD #指定启动容器时执行的命令,可以通过docker run World输出 World(CMD被覆盖)。可以和ENTRYPOINT 组合使用,ENTRYPOINT 定义主命令[“java”, “-jar”],CMD定义可覆盖的命令[“app.jar”],这样在外部未指定的情况下,默认运行app.jar。
- ENTRYPOINT #定义容器启动时运行的主命令,不可被覆盖,除非使用 --entrypoint。
六、docker-compose容器编排
docker compose 是一个用于定义和运行多容器 Docker 应用的工具。它通过一个简单的 YAML文件来配置应用的服务、网络、卷等,然后用一条命令就能启动所有服务。文件名称必须是docker-compose.yml文件,执行docker-compose命令时,当前目录下要有docker-compose.yml文件。
1、docker-compose基本命令
# 启动所有服务(后台运行)
docker-compose up -d
# 停止所有服务
docker-compose down
# 查看服务状态
docker-compose ps
# 查看日志
docker-compose logs -f
# 重启特定服务
docker-compose restart webapp
# 前台运行(查看实时日志)
docker-compose up
# 重新构建镜像并启动
docker-compose up --build
# 执行单个命令
docker-compose exec mysql bash
2、常用的日志命令
# 查看所有服务的全部日志(从启动开始)
docker-compose logs
# 查看特定服务的日志
docker-compose logs <服务名>
# 实时跟踪所有服务的日志(类似tail -f)
docker-compose logs -f
# 组合使用:实时查看特定服务的最后100行
docker-compose logs --tail=100 -f <服务名>
# 查看所有服务最近10分钟的日志
docker-compose logs --since 10m
# 查看指定时间后的日志
docker-compose logs --since "2023-09-10T12:00:00"
# 同时查看多个服务的日志
docker-compose logs -f service1 service2
# 只显示最新日志(不输出历史)
docker-compose logs --since 0s
2、多环境配置
# 基础配置
docker-compose.yml
# 开发环境覆盖配置
docker-compose.override.yml
# 生产环境配置
docker-compose.prod.yml
# 使用方式
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up
3、docker-compose.yml文件编写
version: '3.8' #指定语法版本,docker-compose v2.x支持不写版本,1.x必须写
services: #定义服务列表
mysql: #指定服务名,下面的服务可以通过服务名进行交互
image: mysql:8.0.42 #使用的镜像
container_name: mysql #指定容器名
restart: unless-stopped #设置重启策略,一共有四种策略,no不自定重启(默认)、always总是重启(无论退出状态如何)、on-failure失败时重启(仅当容器非正常退出,即退出码非0时重启)、unless-stopped除非手动停止,否则总是重启(忽略docker stop命令,其他情况都重启)
ports: #设置端口映射,可以设置多个。宿主机端口:容器端口
- "3306:3306"
environment: #设置环境变量。至于下面在设置Mysql的账号信息以及创建库,那是因为官方镜像内置了启动脚本,会自动处理这些环境变量。
MYSQL_ROOT_PASSWORD: root #设置MySQL root用户的密码
MYSQL_DATABASE: nacos_config #容器启动时自动创建的数据库名称
MYSQL_USER: nacos #创建的自定义用户名
MYSQL_PASSWORD: nacos #上述自定义用户的密码
TZ: Asia/Shanghai #设置时区为上海(东八区)
volumes: #配置数据卷/目录挂载,实现数据持久化和初始化
- mysql-data:/var/lib/mysql #mysql-data是Docker管理的命名卷,默认在/var/lib/docker/volumes/目录下面,你也可以自定义
- ./mysql-init.sh:/docker-entrypoint-initdb.d/init.sh #将自己写的mysql-init.sh初始化脚本挂载到容器内的初始化目录,/docker-entrypoint-initdb.d/init.sh是MySQL启动的时候执行的初始化脚本,记得给mysql-init.sh赋予执行权,默认创建的脚本文件只有读写权限没有执行权限。
#- ./mysql-init.sql:/docker-entrypoint-initdb.d/init.sql #同上,但使用SQL文件而非Shell脚本,SQL文件更适合纯数据库操作(如建表、插入初始数据)。
command: #覆盖容器默认的启动命令。就是覆盖dockerfile里面CMD参数。启动命令优先级低到高,ENTRYPOINT、CMD、command。
- --default-authentication-plugin=mysql_native_password #强制使用旧版密码认证插件(兼容老客户端),比如一些老的数据库管理工具也可以登录。
- --character-set-server=utf8mb4 #设置默认字符集为utf8mb4(支持完整Unicode,如emoji)
- --collation-server=utf8mb4_unicode_ci #设置默认排序规则(对多语言文本排序更准确)
healthcheck: #健康检查
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-proot"] #健康检查命令
interval: 5s #每5秒执行一次检查
timeout: 10s #单次检查的超时时间,超过10秒无响应则视为失败。
retries: 15 #连续失败15次后,才标记容器为不健康,如果配置了重启策略的话,会自动重启。
nacos:
image: nacos/nacos-server:v3.0.3
container_name: nacos
restart: unless-stopped
depends_on: #定义服务启动依赖关系,意思是只有当下面的服务满足条件后,才会加载该服务
mysql: #依赖的服务名称(必须是同一 compose 文件中的服务)
condition: service_healthy #条件,必须等待 mysql 服务健康检查通过,才满足条件。这个可以不设置,那么就是等待服务进程启动后就行。
ports:
- "8080:8080" # Nacos Web控制台
- "8848:8848" # gRPC端口
- "9848:9848" # Raft端口
environment:
MODE: standalone
SPRING_DATASOURCE_PLATFORM: mysql
MYSQL_SERVICE_HOST: mysql
MYSQL_SERVICE_PORT: 3306
MYSQL_SERVICE_DB_NAME: nacos_config
MYSQL_SERVICE_USER: nacos
MYSQL_SERVICE_PASSWORD: nacos
# 核心鉴权配置
NACOS_AUTH_ENABLE: "true"
NACOS_AUTH_TOKEN_ENABLE: "true"
NACOS_AUTH_CACHE_ENABLE: "true"
# 使用默认密钥
NACOS_AUTH_TOKEN: "t8adqwIZcxer5mmtLM2gJme5VETsmVfZCT2rkODK5gE="
NACOS_AUTH_IDENTITY_KEY: "serverIdentity"
NACOS_AUTH_IDENTITY_VALUE: "security"
JVM_XMS: 256m
JVM_XMX: 512m
TZ: Asia/Shanghai
volumes:
- /workspace/nacos/logs/:/root/nacos/logs
volumes: # 声明所有需要Docker管理的命名卷(Docker会自动创建),像我这个配置只需要声明一下mysql-data就行了。
mysql-data:
注意:像MySQL这种替换进去的初始化脚本,一定要加上文件执行权限,要不然不会执行。
#查询mysql-init.sh文件权限
ls -l mysql-init.sh
#如果输出显示没有 x(执行)权限,比如:-rw-r--r-- 1 user user 1234 Sep 10 12:34 mysql-init.sh
# 给所有用户添加执行权限(最安全)
chmod +x mysql-init.sh
4、核心指令提取
| 指令 | 作用 |
|---|---|
| version | 指定语法版本 |
| services | 定义服务列表 |
| image | 指定镜像 |
| build | 构建镜像 |
| ports | 端口映射 |
| volumes | 数据卷挂载 |
| environment | 环境变量 |
| depends_on | 依赖顺序 |
| networks | 网络配置 |
| restart | 重启策略 |
5、加入同一个网络
首先说一下,同一 compose 文件内的服务是互通,默认就在同一网络,那么就不需要去自定义一个内网。只有跨 compose 服务需要互通或者需要调整网络参数(如子网),又或者生产环境强化隔离等等情况,才需要去自定义或者加入一个网络。
5.1、自定义或加入已经存在的网络,直接在docker-compose文件默认添加。
networks: # 定义自定义网络
my_network:
#external: true # 表示网络在外部已存在,不写默认是false,会添加一个自定义网络。
driver: bridge # 使用bridge驱动(默认,可省略)
5.2、在服务下面
networks: # 加入同一个自定义网络
- my_network
5.3、查询容器使用的网络和使用指定网络的容器
# 查看所有网络
docker network ls
# 02d7e9ac97e0是容器id,名称和都行。获取使用的网络名称。
docker inspect 02d7e9ac97e0 --format '{{range $net, $config := .NetworkSettings.Networks}}{{$net}}{{end}}'
# 查看my_network网络中有哪些容器,my_network 是自定义的网络名称
docker network inspect my_network --format '{{range .Containers}}{{.Name}} {{end}}'
七、总结
Docker还有一些有趣的用法,这里我只介绍一些常用的用法。这里再给一些建议。
- 如果要应用某一个开源的镜像容器,最好先找到它的官网或者GitHub上先看看文档,因为在启动容器时的一些参数,一般都是镜像官方准备好的,这样才可以更好的使用的容器。
- 容器启动不了,先看容器日志,再针对性解决。
- 如果说外部文件都确定没有错,记得一定要进容器里面看,说不准是没映射进去或者映射错了目录。
- 如果初始化脚本没执行,所有的脚本它都会在工作目录中执行,进去容器里面可以尝试执行一下脚本中的命令。
更多推荐


所有评论(0)