石一歌的Docker基础笔记 [狂神]


Docker

  • 文档
  • 仓库

概述

Docker出现

  • 开发和运维使用两套环境,环境配置十分麻烦(Windows开发,Linux上运行)。
    Docker给以上问题提出了解决方案:
    Java --- Jar(环境)---打包项目带上环境(镜像)---Docker仓库(应用商店)---下载镜像---直接运行
  • Docker的核心思想:隔离。
    即将应用打包装箱,每个箱子是互相隔离的,可以将服务器利用到极致。
虚拟机 Docker
linux centos原生镜像(一个电脑) 隔离镜像(最核心的环境 +jdk +mysql等)
需要开启多个虚拟机 运行镜像就可以了
几GB 几MB

Docker历史

  • 2010年,旧金山成立dotCloud,底层技术为LXC(后被Libcontainer代替)。
  • 基于Go语言,开发内部工具Docker
  • 2013年3月,Solomon?Hykes开源Docker
  • 2014年6月9日, Docker 1.0 版本正式发布。

对比虚拟机

QQ截图20220226225942

Docker特点

  • 不模拟完整的操作系统,系统内核(kernel)非常小,更少的抽象层(GuestOS:如Centos)
  • 容器内的应用直接运行在宿主机的内核,容器本身没有自己的内核,也没有虚拟硬件。
  • 每个容器相互隔离,内部都有属于自己的文件系统,互不影响。

Docker优点

  • 更高效的利用系统资源
  • 更快速的启动时间
  • 一致的运行环境
  • 持续交付和部署
  • 更轻松的迁移
  • 更轻松的维护和扩展

安装

Docker基本组成

QQ截图20220226231532

  • 镜像(image):镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件。它包含运行某个软件所需的所有内容,包括代码、运行时、库、环境变量和配置文件。相当于一个模板,通过这个模板来创建容器服务,可以通过一个镜像创建多个容器。
  • 容器(container):独立运行一个或一组应用/基本命令有:启动,停止,删除等/可理解为一个简单的linux系统。
  • 仓库(repository):存放镜像的地方(公有/私有)

环境准备

内核3.10+,版本7.0+

[root@faetbwac ~]# uname -r
3.10.0-1160.53.1.el7.x86_64
[root@faetbwac ~]# cat /etc/os-release
NAME="CentOS Linux"
VERSION="7 (Core)"
ID="centos"
ID_LIKE="rhel fedora"
VERSION_ID="7"
PRETTY_NAME="CentOS Linux 7 (Core)"
ANSI_COLOR="0;31"
CPE_NAME="cpe:/o:centos:centos:7"
HOME_URL="https://www.centos.org/"
BUG_REPORT_URL="https://bugs.centos.org/"

CENTOS_MANTISBT_PROJECT="CentOS-7"
CENTOS_MANTISBT_PROJECT_VERSION="7"
REDHAT_SUPPORT_PRODUCT="centos"
REDHAT_SUPPORT_PRODUCT_VERSION="7"

安装操作

# 卸载旧Docker
	yum remove docker \
           docker-client \
           docker-client-latest \
           docker-common \
           docker-latest \
           docker-latest-logrotate \
           docker-logrotate \
           docker-engine
# 安装依赖
	yum install -y yum-utils
# 设置阿里云镜像仓库
    yum-config-manager \
       --add-repo \
      https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# 更新yum软件包索引
	yum makecache fast
# 安装docker引擎
	yum install docker-ce docker-ce-cli containerd.io

卸载操作

# 卸载docker引擎
	yum remove docker-ce docker-ce-cli containerd.io
# 删除镜像、容器、数据卷和配置文件
    rm -rf /var/lib/docker
    rm -rf /var/lib/containerd

阿里云镜像加速

mkdir -p /etc/docker
tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://k1boskqx.mirror.aliyuncs.com"]
}
EOF
systemctl daemon-reload
systemctl restart docker

底层原理

Docker是一个Client-Server结构的系统,以守护进程运行在主机上。通过Socket从客户端进行访问。主要组成如下:

  • 服务器,是一种长期运行的程序,称为守护进程
  • REST API,指定程序用来与守护进程对话并指示

命令

20201212210110

帮助命令

命令文档

# docker版本信息
	docker version
# 系统级别的信息,包括镜像和容器的数量
	docker info
# 命令帮助信息
	docker xx --help

服务命令

# 启动docker服务
	systemctl start docker
# 停止docker服务
	systemctl stop docker
# 重启docker服务
	systemctl restart docker
# 查看docker服务状态
	systemctl status docker
# 设置开机启动docker服务
	systenctl enable docker

镜像命令

# 查看本地镜像
	docker images [OPTIONS] [REPOSITORY[:TAG]]
    [options]:  
        -a :列出本地所有的镜像(含中间映像层,默认情况下,过滤掉中间映像层);
        --digests :显示镜像的摘要信息;
        -f :显示满足条件的镜像;
        --format :指定返回值的模板文件;
        --no-trunc :显示完整的镜像信息;
        -q :只显示镜像ID。
# 搜索镜像
	docker search [OPTIONS] TERM
    [options]:  
        --automated :只列出 automated build类型的镜像;
        --no-trunc :显示完整的镜像描述;
        -f <过滤条件>:列出收藏数不小于指定值的镜像。
    参数说明:
        NAME: 镜像仓库源的名称
        DESCRIPTION: 镜像的描述
        OFFICIAL: 是否 docker 官方发布
        stars: 星星数。
        AUTOMATED: 自动构建。
# 拉取镜像
	docker pull [OPTIONS] NAME[:TAG|@DIGEST]
	[options]:  
        -a :拉取所有 tagged 镜像
        --disable-content-trust :忽略镜像的校验,默认开启
	实例:
        [root@faetbwac ~]# docker pull nginx
        Using default tag: latest  # 默认latest
        latest: Pulling from library/nginx
        a2abf6c4d29d: Pull complete  # 分层下载,联合文件系统,不同镜像的相同文件无需再次下载
        a9edb18cadd1: Pull complete 
        589b7251471a: Pull complete 
        186b1aaa4aa6: Pull complete 
        b4df32aa5a72: Pull complete 
        a0bcbecc962e: Pull complete 
        Digest: sha256:0d17b565c37bcbd895e9d92315a05c1c3c9a29f762b011a10c54a66cd53c9b31  # 签名
        Status: Downloaded newer image for nginx:latest
        docker.io/library/nginx:latest  # 真实地址,可直接拉取
# 移除镜像
	docker rmi [OPTIONS] IMAGE [IMAGE...]
	[options]:  
        -f :强制删除;
        --no-prune :不移除该镜像的过程镜像,默认移除;
    docker rmi -f $(docker images -aq)  #全部移除
# 镜像历史
	docker history [OPTIONS] IMAGE
	[options]: 
        -H :以可读的格式打印镜像大小和日期,默认为true;
        --no-trunc :显示完整的提交记录;
        -q :仅列出提交记录ID。

容器命令

# 创建并启动容器
	docker run [OPTIONS] IMAGE [COMMAND] [ARG...]         
    [options]:                  
        --name=容器名 :命名容器以区分不同容器
        -d :在后台运行容器(类似centos的系统容器,必须要指定前台进程)
        -it :使用交互方式运行,进入容器查看内容
        -p :指定容器的端口
            -p  ip:主机端口:容器端口
            -p  主机端口:容器端口(常用)
            -p  容器端口
            容器端口
        -P :随机容器的端口
        --rm :用完即删(测试)
        --net somenetwork :网络配置 
        -e username="ritchie" :设置环境变量
        -v 主机目录:容器目录 :挂载数据卷
        --link 容器名 镜像名 :修改容器hosts文件加入目标容器
    [command]:
    	/bin/bash :控制台
# 查看本地容器
	docker ps [OPTIONS]
	[options]:   
        -a :列出正在运行的容器包括历史容器
        -n=? :显示最近创建的容器
        -q :只显示当前容器的编号
# 启动容器
	docker start [OPTIONS] CONTAINER [CONTAINER...]
# 重启容器
	docker restart [OPTIONS] CONTAINER [CONTAINER...]
# 关闭容器
	docker stop [OPTIONS] CONTAINER [CONTAINER...]
# 强制关闭容器
	docker kill [OPTIONS] CONTAINER [CONTAINER...]
# 删除容器
	docker rm [OPTIONS] CONTAINER [CONTAINER...]
	docker rm -f $(docker ps -aq)  #全部移除
	docker ps -a -q|xargs docker rm  #全部移除
	[options]:
        -f :通过 SIGKILL 信号强制删除一个运行中的容器。
        -l :移除容器间的网络连接,而非容器本身。
        -v :删除与容器关联的卷。
# 查看容器日志
	docker logs [OPTIONS] CONTAINER
	[options]:  
    	-f : 跟踪日志输出
        --since :显示某个开始时间的所有日志
        -t : 显示时间戳
        --tail :仅列出最新N条容器日志
# 查看容器进程
	docker top [OPTIONS] CONTAINER [ps OPTIONS]
# 查看容器元数据
	docker inspect [OPTIONS] NAME|ID [NAME|ID...]
# 查看容器状态
	docker stats [OPTIONS] [CONTAINER...]
# 进入容器
	docker attach [OPTIONS] CONTAINER
	docker exec [OPTIONS] CONTAINER COMMAND [ARG...]
	[options]: 
        -d :分离模式: 在后台运行
        -i :即使没有附加也保持STDIN 打开
        -t :分配一个伪终端
# 退出容器
    Exit(CTRL+d/CTRL+c) :容器停止退出 
    CTRL+p+q :容器不停止退出
# 拷贝文件
	docker cp [OPTIONS] CONTAINER:SRC_PATH DEST_PATH|-
	docker cp [OPTIONS] SRC_PATH|- CONTAINER:DEST_PATH
	[options]: 
		-L :保持源目标中的链接

可视化

Portainer

查找到商业版需要许可证,尽管有5个免费的,还是选择社区版。

官方提示portainer/portainer存储库已弃用。这里我直接最新版,经测试2.9的汉化依旧可以使用。

[Portainer官网](安装 Portainer CE - Portainer 文档)

汉化帖子

# 部署Portainer
	docker volume create portainer_data
    docker run -d -p 8000:8000 -p 9443:9443 --name portainer \
    --restart=always \
    -v /var/run/docker.sock:/var/run/docker.sock \
    -v portainer_data:/data \
    -v /root/public:/public \
    portainer/portainer-ce:2.11.1
    [options]: 
        -d:容器在后台运行;
        -p 8000:8000 :端口映射
        –restart 标志会检查容器的退出代码,并据此来决定是否要重启容器,默认是不会重启。
        –restart=always:自动重启该容器
        -v /var/run/docker.sock:/var/run/docker.sock :把宿主机的Docker守护进程(Docker daemon)默认监听的Unix域套接字挂载到容器中
        -v portainer_data:/data :把宿主机portainer_data数据卷挂载到容器/data目录
        –name prtainer-test : 给容器起名为portainer
# 汉化Portainer
	下载汉化文件,解压出public文件夹传输至系统root目录下

Rancher(CI/CD)

镜像详解

QQ截图20220301220544

UnionFS(联合文件系统)

  • 联合文件系统(UnionFS)是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下。联合文件系统是 Docker 镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。
  • 特性:一次同时加载多个文件系统,但从外面看起来只能看到一个文件系统。联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录。

镜像加载原理

Docker的镜像实际由一层一层的文件系统组成:

  • bootfs(boot file system)主要包含bootloader和kernel。bootloader主要是引导加载kernel,完成后整个内核就都在内存中了。此时内存的使用权已由bootfs转交给内核,系统卸载bootfs。可以被不同的Linux发行版公用。
  • rootfs(root file system),包含典型Linux系统中的/dev,/proc,/bin,/etc等标准目录和文件。rootfs就是各种不同操作系统发行版(Ubuntu,Centos等)。因为底层直接用Host的kernel,rootfs只包含最基本的命令,工具和程序就可以了。

分层理解

  • 所有的Docker镜像都起始于一个基础镜像层,当进行修改或增加新的内容时,就会在当前镜像层之上,创建新的容器层。
  • 容器在启动时会在镜像最外层上建立一层可读写的容器层(R/W),而镜像层是只读的(R/O)。

提交容器

# 提交容器为新的镜像
	docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
	[options]: 
        -a :提交的镜像作者
        -c :使用Dockerfile指令来创建镜像
        -m :提交时的说明文字
        -p :在commit时,将容器暂停

数据卷

为了实现数据持久化,使容器之间可以共享数据。可以将容器内的目录,挂载到宿主机上或其他容器内,实现同步和共享的操作。即使将容器删除,挂载到本地的数据卷也不会丢失。

数据卷命令

# 数据卷命令
	docker volume COMMAND
	Commands:
      create      创建卷
      inspect     展示卷信息
      ls          列出所有卷
      prune       移除所有不使用的卷
      rm          移除卷

挂载数据卷

QQ截图20220302185925

QQ截图20220302185936

QQ截图20220302185947

# 冷挂载(容器启动时挂载/dockerfile挂载)
	Bind(指定路径挂载)
		-v /主机路径:容器内路径        
	Volume(Docker路径挂载)
		-v  容器内路径 :匿名挂载
		-v  卷名:容器内路径 :具名挂载
	tmpfs(内存挂载)
		--tmpfs 容器内路径
# 热挂载
	参照文末链接,很少这么做
  • docker rm -v 命令不会删除具名挂载和指定路径挂载的卷,而匿名挂载会被删除

  • -v 容器内路径:ro/rw 可改变读写权限

    • ro readonly #只读
    • rw readwrite #可读可写
Bind Volume tmpfs
volume 位置 可指定任意位置 /var/lib/docker/volumes/... 宿主机内存中
对已有mount point 影响 隐藏并替换为 volume 原有数据复制到 volume -
是否支持单个文件 支持 不支持,只能是目录 -
权限控制 可设置为只读,默认为读写权限 可设置为只读,默认为读写权限 -
移植性 移植性弱,与 host path 绑定 移植性强,无需指定 host 目录 -
是否支持持久化 支持 支持 不支持

挂载复制

这里狂神的用的名字是容器数据卷,查看容器的元数据可知,多个容器挂载到宿主的同一位置,称为挂载复制更恰当。不论父容器挂载方式如何,都可以使用。

 # 挂载复制
 	--volumes-from 容器名称

Dockerfile挂载

在创建镜像的过程中可以指定挂载卷(匿名挂载)。

FROM centos
VOLUME ["/volume1"]
CMD echo "----end----"
CMD /bin/bash

Dockerfile

用来构建Docker镜像的文件。

Dockerfile构建镜像步骤

  • 编写Dockerfile文件
  • 执行docker build命令

Dockerfile文件

  • 构建过程

    • 每个保留关键字(指令)忽略大小写,建议大写

    • 从上到下顺序执行

    • "#" 表示注释

    • 每一个指令都会创建提交一个新的镜像层并提交

  • Dockerfile指令

    命令 效果
    FROM 基础镜像:Centos/Ubuntu
    MAINTAINER 镜像作者+邮箱
    RUN 镜像构建的时运行命令
    ADD 为镜像添加内容(压缩包)
    WORKDIR 镜像工作目录(进入容器时的目录)
    VOLUME 挂载的目录
    EXPOSE 暴露端口配置
    CMD/ENTRYPOINT 容器启动时运行命令
    COPY 类似于ADD,将文件拷贝到镜像中
    ENV 构建时设置环境变量
    ONBUILD 为镜像添加触发器。其参数是任意一个Dockerfile 指令。构建子镜像时执行。

构建镜像

构建文件名为Dockerfile的,可以省略末尾的.

# Dockerfile构建镜像
	docker build [OPTIONS] PATH | URL | -
	[options]: 
        --build-arg=[] :设置镜像创建时的变量;
        --cpu-shares :设置 cpu 使用权重;
        --cpu-period :限制 CPU CFS周期;
        --cpu-quota :限制 CPU CFS配额;
        --cpuset-cpus :指定使用的CPU id;
        --cpuset-mems :指定使用的内存 id;
        --disable-content-trust :忽略校验,默认开启;
        -f :指定要使用的Dockerfile路径;
        --force-rm :设置镜像过程中删除中间容器;
        --isolation :使用容器隔离技术;
        --label=[] :设置镜像使用的元数据;
        -m :设置内存最大值;
        --memory-swap :设置Swap的最大值为内存+swap,"-1"表示不限swap;
        --no-cache :创建镜像的过程不使用缓存;
        --pull :尝试去更新镜像的新版本;
        --quiet, -q :安静模式,成功后只输出镜像 ID;
        --rm :设置镜像成功后删除中间容器;
        --shm-size :设置/dev/shm的大小,默认值是64M;
        --ulimit :Ulimit配置。
        --squash :将 Dockerfile 中所有的操作压缩为一层。
        --tag, -t :镜像的名字及标签,通常 name:tag 或者 name 格式;可以在一次构建中为一个镜像设置多个标签。
        --network :默认 default。在构建期间设置RUN指令的网络模式

CMD&ENTRYPOINT

  • exec模式和shell模式

    • exec模式
      • 容器中的1号进程是任务进程
      • 不会直接通过shell执行命令,无法直接获取环境变量,可以执行shell命令获取环境变量
    • shell模式
      • 容器中的1号进程不是任务进程,而是bash进程
      • 会直接通过shell执行命令,可以直接获取环境变量
  • CMD指令和ENTRYPOINT指令

    • CMD指令

      docker run 时可以用命令行参数覆盖CMD指令(全模式)

      dockerfile中的多个CMD命令,会被覆盖,只保留最后一条

      • ENTRYPOINT提供默认参数

        CMD ["param1","param2"]
        
      • exec模式

        CMD ["executable","param1","param2"]
        
      • shell模式

        CMD command param1 param2
        
    • ENTRYPOINT指令

      docker run 时可以用命令行参数追加到ENTRYPOINT指定命令的参数列表中(exec模式)

      dockerfile中的多个ENTRYPOINT命令,会被覆盖,只保留最后一条

      • exec模式

        命令行上指定的参数会作为参数添加到 ENTRYPOINT 指定命令的参数列表中

        ENTRYPOINT ["executable", "param1", "param2"] 
        
      • shell模式

        完全忽略命令行参数

        ENTRYPOINT command param1 param2
        
    • 同时使用

      • 如果 ENTRYPOINT 使用了 shell 模式,CMD 指令会被忽略
      • 如果 ENTRYPOINT 使用了 exec 模式,CMD 指定的内容被追加为 ENTRYPOINT 指定命令的参数
      • 如果 ENTRYPOINT 使用了 exec 模式,CMD 也应该使用 exec 模式

      952033-20180223131745112-1674454515

发布镜像

# 登录镜像仓库
	docker login [OPTIONS] [SERVER]
	[options]: 
        -u :登陆的用户名
        -p :登陆的密码
# 推送镜像
	docker push [OPTIONS] NAME[:TAG]
	[options]:
		--disable-content-trust :忽略镜像的校验,默认开启

网络

dockerm默认提供的网络模式

  • bridge:多由于独立container之间的通信
  • host: 直接使用宿主机的网络,端口也使用宿主机的
  • overlay:当有多个docker主机时,跨主机的container通信
  • macvlan:每个container都有一个虚拟的MAC地址
  • none: 禁用网络

网络命令

# 网络命令
	docker network COMMAND
	Commands:
        connect 将某个容器连接到一个docker网络
        create 创建一个docker局域网络
        disconnect 将某个容器退出某个局域网络
        inspect 显示某个局域网络信息
        ls 显示所有docker局域网络
        prune 删除所有未引用的docker局域网络
        rm 删除docker网络

docker0

  • 云服务器网络

    查看网络ip addr

    • 环回地址

      # lo
      	inet 127.0.0.1/8
      
    • 内网地址

      # eth0
      	172.19.132.127/20
      
    • Docker网络地址

      # docker0: 
          172.17.0.1/16
      
  • docker0

    docker网桥,Docker中的所有容器通过虚拟网卡连接到docker0进行网络访问,容器之间也可以通过docker0访问,

    原理:新建容器时创建在虚拟接网卡(veth-pair),一端在默认的docker0或指定网桥上,一端在放到新容器中修改名字作为eth0, 从网桥可用地址段中获取一个空闲地址分配给容器的 eth0,并配置默认路由到桥接网卡

    下面介绍几种查看容器网络的方法

    • ip addr

      直接进入容器执行ip addr命令即可。

      需要注意的是最新版tomcat镜像没有ip addr命令,需要先进行apt update && apt install -y iproute2命令安装相关工具

    • docker inspect

      查看容器的元数据,NetworkSettings字段中Networks有详细的数据

      docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' 可以直接提取容器的ip数据

    • docker network inspect

      查看网络元数据,Containers字段也详细介绍ip数据

20210131140833

容器互联

容器没有ping命令,可以执行apt-get update && apt install iputils-ping安装

  • --link

可以通过docker run --link CONTAINER IMAGE,在启动的容器内的hosts文件写入目标容器的地址,从而直接通信

  • 自定义网络

    加入同一自定义网络的不同容器间可通过ip地址或容器名/id连通

    # 创建自定义网络
    	docker network create [OPTIONS] NETWORK
    	[options]:
        	-d :网络类型
        	--subnet :子网地址 
        	--gateway :网关地址
    # 启动容器指定网络
    	docker run -itd --network NETWORK IMAGE
    
  • 容器连通网络

    可以将原有容器添加目标容器的网段,相当于原有容器在目标容器添加一个虚拟ip,实现跨网段的容器互联

    # 容器连通网络
    	docker network connect [OPTIONS] NETWORK CONTAINER
    

参考链接

  • 狂神说docker(最全笔记)
  • 为什么docker不适合mysql_为什么不建议把数据库部署在Docker容器内
  • 给一个正在运行的Docker容器动态添加Volume
  • Docker基础-19-网络-bridge模式和docker0详解
  • docker network create