一、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
  1. nginx #是镜像名
  2. :latest #指定要拉取镜像的版本,不写默认拉latest版本,也就是最新版本。

2、查看本地镜像

docker images

3、启动容器

docker run -d --name nginx -p 8080:80 -v /data/nginx:/opt/nginx/html nginx
  1. docker run #创建并启动容器命令,必写。
  2. -d #启动的容器后台运行的意思,非必写。
  3. –name #指定容器的名称,非必写。
  4. -p #指定映射宿主机和容器的端口,宿主机端口:容器的端口,非必写。
  5. -v #配置数据卷/目录挂载,实现数据持久化和初始化。把宿主机的配置文件映射到容器里面,又或者把容器里面生成的文件存储到宿主机上来。宿主机的目录:容器应用程序的目录。
  6. 最后的nginx,是镜像名称,你要创建并启动什么容器,就写什么容器的名称。

4、查看运行中的容器信息

docker ps

5、进入容器

docker exec -it nginx bash
  1. -it #打开终端交互(进入容器操作)
  2. nginx #容器名称
  3. 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 .
  1. -t #构建镜像的名称。
  2. . #表示 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"]
  1. FROM #构建镜像需要一个基础镜像,centos:7.9.2009 就是一个基础镜像
  2. MAINTAINER #声明镜像维护者信息,标明镜像作者是 jnyw(已弃用语法,现在 推荐使用 LABEL)
  3. RUN mkdir -p #RUN 在基础镜像上要执行的命令。mkdir 创建目录结构,-p参数确保父目录不存在时自动创建。
  4. WORKDIR #设置工作目录,后续命令(如 ADD, RUN等)默认在此目录下执行,容器启动后也会自动进入此目录。
  5. ENV #设置环境变量。Spring Boot会自动将环境变量智能覆盖到应用配置中,所以可以达到Java的-Dproperties=true启动参数类似的效果,但不完全等效,而且-D优先级更高。
  6. ADD #将宿主机目录的文件拷贝到容器中并自动解压,宿主机的文件与 dockerfile 位于相同目录中
  7. CMD #指定启动容器时执行的命令,可以通过docker run World输出 World(CMD被覆盖)。可以和ENTRYPOINT 组合使用,ENTRYPOINT 定义主命令[“java”, “-jar”],CMD定义可覆盖的命令[“app.jar”],这样在外部未指定的情况下,默认运行app.jar。
  8. 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还有一些有趣的用法,这里我只介绍一些常用的用法。这里再给一些建议。

  1. 如果要应用某一个开源的镜像容器,最好先找到它的官网或者GitHub上先看看文档,因为在启动容器时的一些参数,一般都是镜像官方准备好的,这样才可以更好的使用的容器。
  2. 容器启动不了,先看容器日志,再针对性解决。
  3. 如果说外部文件都确定没有错,记得一定要进容器里面看,说不准是没映射进去或者映射错了目录。
  4. 如果初始化脚本没执行,所有的脚本它都会在工作目录中执行,进去容器里面可以尝试执行一下脚本中的命令。
Logo

码道开发者社区,聚焦华为云码道 CodeArts 代码智能体,沉淀 Agent、Skill、鸿蒙开发实战内容,供开发者查阅资料、交流技术、分享工程实践

更多推荐