Video Reference:【尚硅谷】Docker迅速入门丨零基础学Docker
1 Docker 简介
:::color1 前提知识:
强制:熟悉 Linux 常用命令,和相关背景知识
建议:Maven / Git 相关的知识
下载链接:http://www.atguigu.com/download.shtml
:::
1.1 Docker 是什么
问题:为什么会出现 Docker 出现?
一款产品从开发到上线,从操作系统,到运行环境,再到应用配置。作为开发+运维之间的协作我们需要关心很多东西,这也是很多互联网公司都不得不面对的问题,特别是各种版本的迭代之后,不同版本环境的兼容,对运维人员都是考验。
Docker之所以发展如此迅速,也是因为它对此给出了一个标准化的解决方案。
环境配置如此麻烦,换一台机器,就要重来一次,费力费时。很多人想到,能不能从根本上解决问题,软件可以带环境安装?也就是说,安装的时候,把原始环境一模一样地复制过来。开发人员利用Docker可以消除协作编码时“在我的机器上可正常工作”的问题。
之前在服务器配置一个应用的运行环境,要安装各种软件,就拿尚硅谷电商项目的环境来说吧,Java/TomcatMySQLJDBC驱动包等;安装和配置这些东西有多麻烦就不说了,它还不能跨平台。假如我们是在Windows上安装的这些环境,到了Linux又得重新装。况丘就算不跨操作系统,换另一台同样操作系统的服务器,要移植应用也是非常麻烦的。
传统上认为,软件编码开发/测试结束后,所产出的成果即是程序或是能够编译执行的二进制字节码等(java为例)。而为了让这些程序可以顺利执行,开发团队也得准备完整的部署文件,让维运团队得以部署应用程式,开发需要清楚的告诉运维部署团队,用的全部配置文件+所有软件环境。不过,即便如此,仍然常常发生部署失败的状况。Docker镜像的设计,使得Docker得以打破过去「程序即应用」的观念。透过镜像(images)将作业系统核心除外,运作应用程式所需要的系统环境,由下而上打包,达到应用程式跨平台间的无缝接轨运作。
:::color1 Java 虚拟机的概念:一次编译,处处运行。
Docker 的理念:一次构建,处处运行。
:::
Docker 理念
Docker是基于Go语言实现的云开源项目。
Docker的主要目标是“Build,Ship and Run Any App , Anywhere”,也就是通过对应用组件的封装、分发、部署、运行等生命周期的管理,使用户的APP(可以是一个WEB应用或数据库应用等等)及其运行环境能够做到“一次封装,到处运行”。
Linux容器技术的出现就解决了这样一个问题,而Docker就是在它的基础上发展过来的。将应用运行在Docker容器上面,而Docker容器在任何操作系统上都是一致的,这就实现了跨平台、跨服务器。只需要一次配置好环境,换到别的机子上就可以一键部署好,大大简化了操作。
一句话
解决了运行环境和配置问题软件容器,方便做持续集成并有助于整体发布的容器虚拟化技术。
1.2 Docker 能干嘛
1.2.1 之前的虚拟机技术
虚拟机( Virtual Machine )就是带环境安装的一种解决方案。
它可以在一种操作系统里面运行另一种操作系统,比如在Windows系统里面运行Linux系统。应用程序对此毫无感知,因为虚拟机看上去跟真实系统一模一样,而对于底层系统来说,虚拟机就是一个普通文件,不需要了就删掉,对其他部分毫无影响。这类虚拟机完美的运行了另一套系统,能够使应用程序,操作系统和硬件三者之间的逻辑不变。![💎3 [尚硅谷-Docker] Docker迅速入门丨零基础学Docker - 图4](/uploads/projects/seekerzw@yaaygq/be1405a274271a6fd61d1790158e64e3.png)
![💎3 [尚硅谷-Docker] Docker迅速入门丨零基础学Docker - 图5](/uploads/projects/seekerzw@yaaygq/c1188b7e414beb832e5708181f7007fd.png)
Docker化之后只需要交付少量容器镜像文件,在正式生产环境加载镜像并运行即可,应用安装配置在镜像里已经内置好,大大节省部署和测试验证时间
:::
- 更便捷的升级和扩缩容
:::color1
随着微服务架构和Docker的发展,大量的应用会通过微服务方式架构,应用的开发构建将变成搭乐高积木一样,每个Docker容器将变成一块“积木”,应用的升级将变得非常容易。当现有的容器不足以支撑业务处理时,可以通过镜像运行新的容器进行快速扩容缩容,使得应用系统的扩容从原来的小时级变成分钟级甚至是秒级:::
- 更简单的系统运维
:::color1
应用容器化运行后,生产环境运行的应用可与开发。测试环境的应用高度一致,容器会将应用程序相关的环境和状态完全封装起来,不会因为底层基础架构和操作系统的不一致给应用带来影响,产生新的BUG。当出现出现异常时,也可以通过测试环境的相同容器进行快速定位和修复。:::
- 更高效的计算资源
:::color1
<font style="color:rgb(119, 0, 136);">传统虚拟机技术是硬件级虚拟化,Docker是内核级虚拟化</font>
,其不像传统的虚拟化技术一样需要额外的Hypervisor的支持,所以在一台物理机上可以运行很多个容器实例,可大大提升物理服务器的CPU和内存的利用率。
:::
1.2.4 企业级
Docker借鉴了标准集装箱的观念,标准集装箱将货物运往世界各地,Docker将这个模型运用到了自己的设计中,唯一不同的是:集装箱运输货物,而Docker运输软件。Docker、Mesos等容器新技术使大规模动态调度成为可能。
- 更轻量:基于容器的虚拟化,仅包含业务运行所需的runtime环境,CentOS/Ubuntu基础镜像仅170M;宿主机可部署100~1000个容器
- 更高效:无操作系统虚拟化开销
- 计算:轻量,无额外开销
- 存储:系统盘aufs/dm/overlayfs;数据盘volume
- 网络:宿主机网络,NS隔离
- 更敏捷、更灵活:
- 分层的存储和包管理,devops理念
- 支持多种网络配置
哪些企业在使用?
- 新浪
- 美团
- 腾讯
- 华为等企业
1.3 Docker 去哪下
- 官网
Docker 官网:https://www.docker.com/
Docker 中文官网:https://www.docker-cn.com/ (目前已关闭该站点)
- 仓库
DockerHub 官网:https://hub.docker.com/ ( 用于保存镜像 )
:::color1 Docker 的三大特征:容器,镜像,仓库
Java 对象的三大特征:封装,继承,多态
:::
2 Docker 安装
2.1 前提说明
CentOS Docker 安装:
Docker支持以下的CentOS版本:
- CentOS 7(64-bit)
- CentOS 6.5(64-bit)或更高的版本
前提条件:
目前,CentOS仅发行版本中的内核支持 Docker。
Docker运行在CentOS 7 上,要求系统为64位、系统内核版本为3.10以上。
Docker运行在CentOS-6.5或更高的版本的CentOS 上,要求系统为64位、系统内核版本为 2.6.32 - 431 或者更高版本。
查看自己的内核:
uname 命令用于打印当前系统相关信息(内核版本号,硬件架构,主机名称和操作系统类型等)
uname -r
查看已安装的 CentOS 版本信息
cat /etc/redhat-release
2.2 Docker 的基础组成
2.2.1 Docker 的架构图
- 镜像(Image)
Docker镜像(Ilmage)就是一个只读的模板。镜像可以用来创建Docker容器,一个镜像可以创建很多容器。
容器与镜像的关系类似于面向对象编程中的对象与类。
Docker | 面向对象 |
---|---|
容器 | 对象 |
镜像 | 类 |
- 容器(Container)
Docker利用容器(Container)独立运行的一个或一组应用。容器是用镜像(Image)创建的运行实例。
它可以被启动、开始、停止、删除。每个容器都是相互隔离的、保证安全的平台。
可以把容器看做是一个简易版的Linux环境(包括root用户权限、进程空间、用户空间和网络空间等)和运行在其中的应用程序。 容器的定义和镜像几乎一模一样,也是一堆层的统一视角,唯一区别在于容器的最上面那一层是可读可写的。 3. 仓库(Repository) 仓库(Repository)是集中存放镜像文件的场所。 仓库(Repository)和仓库注册服务器(Registry)是有区别的。仓库注册服务器上往往存放着多个仓库,每个仓库中又包含了多个镜像,每个镜像有不同的标签(tag,类似于版本号)。 仓库分为公开仓库(Public)和私有仓库(Private)两种形式。 最大的公开仓库是Docker Hub(https://hub.docker.com/)), 存放了数量庞大的镜像供用户下载。国内的公开仓库包括阿里云、网易云等。- 小总结
需要正确的理解 仓库 / 镜像 / 容器 这几个概念:
Docker本身是一个容器运行载体或称之为容器管理引擎。我们把应用程序和配置依赖打包好形成一个可交付的运行环境,这个打包好的运行环境就似乎image镜像文件。只有通过这个镜像文件才能生成 Docker 容器。image文件可以看作是容器的模板。Docker 根据 image文件生成容器的实例。同一个image文件,可以生成多个同时运行的容器实例。 image 文件生成的容器实例,本身也是一个文件,称为镜像文件。 一个容器运行一种服务,当我们需要的时候,就可以通过docker客户端创建一个对应的运行实例,也就是我们的容器。 *至于仓储,就是放了一堆镜像的地方,我们可以把镜像发布到仓储中,需要的时候从仓储中拉下来就可以了。 ## 2.3 安装步骤 ### 2.3.1 CentOS 6 安装 Docker(目前内核已不再适配) 1. yum install -y epel-releasebash
# Docker使用EPEL发布,RHEL系的OS首先要确保已经持有EPEL仓库,否则先检查OS的版本,然后安装相应的EPEL包
yum install -y epel-release
# 使用阿里云的epel源
# CentOS 6操作系统
wget -O /etc/yum.repos.d/epel.repo https://mirrors.aliyun.com/repo/epel-archive-6.repo
# CentOS 7作系统
wget -O /etc/yum.repos.d/epel.repo https://mirrors.aliyun.com/repo/epel-7.repo
2. yum install -y docker-io
bash
yum install -y docker-io
3. 安装后的配置文件:/etc/sysconfig/docker
bash
# CentOS 6系统拥有一个配置文件
vim /etc/sysconfig/docker
4. 启动 Docker 后台服务:service docker start
bash
# CentOS 6系统启动服务
service docker start
chkconfig --add docker
# CentOS 7系统启动服务
systemctl enable --now docker
5. docker version 进行验证
bash
docker version
### 2.3.2 CentOS 7 安装 Docker
参考Docker官网
> https://docs.docker.com/install/linux/docker-ce/centos/
>
> Docker-CE 社区版,Docker-EE 企业版
>
bash
~ sudo yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
~ sudo yum install -y yum-utils
~ sudo yum-config-manager \
--add-repo \
https://download.docker.com/linux/centos/docker-ce.repo
~ sudo yum install docker-ce docker-ce-cli containerd.io docker-compose-plugin
~ sudo systemctl enable --now docker
+ 使用脚本直接安装Docker
bash
#!/bin/bash
DOCKER_VERSION="20.10.10"
#UBUNTU_DOCKER_VERSION="5:${DOCKER_VERSION}~3-0~`lsb_release -si`-`lsb_release -cs`"
DOCKER_COMPOSE_VERSION=1.29.2
DOCKER_COMPOSE_FILE=docker-compose-Linux-x86_64
COLOR_SUCCESS="echo -e \\033[1;32m"
COLOR_FAILURE="echo -e \\033[1;31m"
END="\033[m"
. /etc/os-release
color () {
RES_COL=60
MOVE_TO_COL="echo -en \\033[${RES_COL}G"
SETCOLOR_SUCCESS="echo -en \\033[1;32m"
SETCOLOR_FAILURE="echo -en \\033[1;31m"
SETCOLOR_WARNING="echo -en \\033[1;33m"
SETCOLOR_NORMAL="echo -en \E[0m"
echo -n "$1" && $MOVE_TO_COL
echo -n "["
if [ $2 = "success" -o $2 = "0" ] ;then
${SETCOLOR_SUCCESS}
echo -n $" OK "
elif [ $2 = "failure" -o $2 = "1" ] ;then
${SETCOLOR_FAILURE}
echo -n $"FAILED"
else
${SETCOLOR_WARNING}
echo -n $"WARNING"
fi
${SETCOLOR_NORMAL}
echo -n "]"
echo
}
install_docker(){
if [ $ID = "centos" -o $ID = "rocky" ];then
if [ $VERSION_ID = "7" ];then
cat > /etc/yum.repos.d/docker.repo <<EOF
[docker]
name=docker
gpgcheck=0
#baseurl=https://mirrors.aliyun.com/docker-ce/linux/centos/7/x86_64/stable/
baseurl=https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/centos/7/x86_64/stable/
EOF
else
cat > /etc/yum.repos.d/docker.repo <<EOF
[docker]
name=docker
gpgcheck=0
#baseurl=https://mirrors.aliyun.com/docker-ce/linux/centos/8/x86_64/stable/
baseurl=https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/centos/8/x86_64/stable/
EOF
fi
yum clean all
${COLOR_FAILURE} "Docker有以下版本"${END}
yum list docker-ce --showduplicates
${COLOR_FAILURE}"5秒后即将安装: docker-"${DOCKER_VERSION}" 版本....."${END}
${COLOR_FAILURE}"如果想安装其它Docker版本,请按ctrl+c键退出,修改版本再执行"${END}
sleep 5
yum -y install docker-ce-$DOCKER_VERSION docker-ce-cli-$DOCKER_VERSION \
|| { color "Base,Extras的yum源失败,请检查yum源配置" 1;exit; }
else
dpkg -s docker-ce &> /dev/null && $COLOR"Docker已安装,退出" 1 && exit
apt update || { color "更新包索引失败" 1 ; exit 1; }
apt -y install apt-transport-https ca-certificates curl software-properties-common || \
{ color "安装相关包失败" 1 ; exit 2; }
curl -fsSL https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/ubuntu/gpg | sudo apt-key add -
add-apt-repository "deb [arch=amd64] https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/ubuntu $(lsb_release -cs) stable"
apt update
${COLOR_FAILURE} "Docker有以下版本"${END}
apt-cache madison docker-ce
${COLOR_FAILURE}"5秒后即将安装: docker-"${UBUNTU_DOCKER_VERSION}" 版本....."${END}
${COLOR_FAILURE}"如果想安装其它Docker版本,请按ctrl+c键退出,修改版本再执行"${END}
sleep 5
apt -y install docker-ce=${UBUNTU_DOCKER_VERSION} docker-ce-cli=${UBUNTU_DOCKER_VERSION}
fi
if [ $? -eq 0 ];then
color "安装软件包成功" 0
else
color "安装软件包失败,请检查网络配置" 1
exit
fi
mkdir -p /etc/docker
tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://po13h3y1.mirror.aliyuncs.com"],
"insecure-registries": ["harbor.kubesphere.com:80"]
}
EOF
systemctl daemon-reload
systemctl enable docker
systemctl restart docker
docker version && color "Docker 安装成功" 0 || color "Docker 安装失败" 1
echo 'alias rmi="docker images -qa|xargs docker rmi -f"' >> ~/.bashrc
echo 'alias rmc="docker ps -qa|xargs docker rm -f"' >> ~/.bashrc
}
install_docker_compose(){
if [ $ID = "centos" -o $ID = "rocky" ];then
${COLOR_SUCCESS}"开始安装 Docker compose....."${END}
sleep 1
if [ ! -e ${DOCKER_COMPOSE_FILE} ];then
curl -L https://github.com/docker/compose/releases/download/${DOCKER_COMPOSE_VERSION}/${DOCKER_COMPOSE_FILE} -o /usr/bin/docker-compose
else
mv ${DOCKER_COMPOSE_FILE} /usr/bin/docker-compose
fi
chmod +x /usr/bin/docker-compose
else
apt -y install docker-compose
fi
if docker-compose --version ;then
${COLOR_SUCCESS}"Docker Compose 安装完成"${END}
else
${COLOR_FAILURE}"Docker compose 安装失败"${END}
exit
fi
}
install_docker
install_docker_compose
## 2.4 永远的 Hello World
### 2.4.1 阿里云镜像加速
阿里云镜像加速是什么
> 开放云原生应用-云原生(Cloud Native)-云原生介绍 - 阿里云
>
注册一个属于自己的阿里云账户(可复用淘宝账号)
获得加速器地址连接
> 使用容器镜像服务
>
![💎3 [尚硅谷-Docker] Docker迅速入门丨零基础学Docker - 图10](/uploads/projects/seekerzw@yaaygq/cc06b3ee1d9a3a002f9ec3c83aa96138.png)
<font style="color:#E8323C;">https://xxx.mirror.aliyuncs.com</font>
CentOS 6 的Docker 加速器配置
vim /etc/sysconfig/docker
将获得的自己账户下的阿里云加速地址配置添加到
other_args="--registry-mirror=https://自己的账号加速信息.mirror.aliyuncs.com"
:::
以下操作是 CentOS 7 的Docker 加速器配置
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://po13h3y1.mirror.aliyuncs.com"]
}
EOF
重新启动Docker后台服务: service docker restart
~ sudo systemctl daemon-reload
~ sudo systemctl restart docker
Linux系统下配置完加速器需要检查是否生效
~ docker info | grep -A 1 "Registry Mirrors"
Registry Mirrors:
https://si7y70hh.mirror.aliyuncs.com/
2.4.2 网易云镜像加速
基本同上述阿里云,推荐使用阿里云镜像加速器。
配置的Json串的地方不同了:
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["http://hub-mirror.c.163.com"]
}
EOF
2.4.3 启动 Docker 后台容器(测试运行 hello-world)
docker run hello-world
# 由于本地没有hello-world这个镜像,所以会下载一个hellow-world的镜像,并在容器中内运行
:::color1 输出这段提示以后,hello world 就会停止运行,容器自动终止
:::
- Docker run 流程
2.5 底层原理
2.5.1 Docker 是怎么工作的?
Docker是一个Client-Server结构的系统,Docker守护进程运行在主机上,然后通过Socket连接从客户端访问,守护进程从客户端接受命令并管理运行在主机上的容器。容器,是一个运行时环境,就是我们前面说到的集装箱。
2.5.2 为什么 Docker 比较 VM 快
问题:为什么 Docker 会比 VM 虚拟机快?
(1)**<font style="color:#E8323C;">Docker 有着比虚拟机更少的抽象层</font>**
由于 Docker 不需要 Hypervisor(虚拟机)实现硬件资源虚拟化,运行在 Docker 容器上的程序直接使用的都是实际物理机的硬件资源。因此CPU,内存利用率上 Docker 将会在效率上有明显优势。虚拟机需要实现硬件资源的虚拟化。
(2)**<font style="color:#E8323C;">Docker 利用的是宿主机的内核,而不需要加载操作系统OS内核</font>**
当新建一个容器时,Docker 不需要和虚拟机一样重新加载一个操作系统内核。进而避免引寻,加载操作系统内核返回等比较费时费力资源的过程,当新建一个虚拟机时,虚拟机软件需要重新加载OS,返回新建过程都是分钟级别。而Docker由于直接利用宿主机的操作系统,则省略了返回过程,因此创建一个容器只需要几秒钟。
:::color1 Docker 将传统的虚拟化技术中的 Guest OS 和 Hypervisor 虚拟化层给替换成了 Docker Engine。
:::
Docker容器 | 虚拟机(VM) | |
---|---|---|
操作系统 | 与宿主机共享OS | 宿主机OS上运行虚拟机OS |
存储大小 | 镜像小,便于存储与传输 | 镜像庞大(vmdk,vdi,iso等) |
运行性能 | 几乎无额外性能损失 | 操作系统额外的CPU,内存消耗 |
移植性 | 轻便,灵活,适用于Linux | 笨重,与虚拟化技术耦合度高 |
硬件亲和性 | 面向软件运维者 | 面向硬件运维者 |
部署速度 | 快速,秒级 | 较慢,10s以上 |
3 Docker 常用命令
3.1 帮助命令
:::color1 docker version
docker info
docker —help
:::
~ docker version
Client: Docker Engine - Community
Version: 20.10.10
API version: 1.41
Go version: go1.16.9
Git commit: b485636
Built: Mon Oct 25 07:44:50 2021
OS/Arch: linux/amd64
Context: default
Experimental: true
Server: Docker Engine - Community
Engine:
Version: 20.10.10
API version: 1.41 (minimum version 1.12)
Go version: go1.16.9
Git commit: e2f740d
Built: Mon Oct 25 07:43:13 2021
OS/Arch: linux/amd64
Experimental: false
containerd:
Version: 1.6.6
GitCommit: 10c12954828e7c7c9b6e0ea9b0c02b01407d3ae1
runc:
Version: 1.1.2
GitCommit: v1.1.2-0-ga916309
docker-init:
Version: 0.19.0
GitCommit: de40ad0
~ docker info
Client:
Context: default
Debug Mode: false
Plugins:
app: Docker App (Docker Inc., v0.9.1-beta3)
buildx: Build with BuildKit (Docker Inc., v0.6.3-docker)
scan: Docker Scan (Docker Inc., v0.17.0)
Server:
Containers: 1
Running: 0
Paused: 0
Stopped: 1
Images: 1
Server Version: 20.10.10
Storage Driver: overlay2
Backing Filesystem: xfs
Supports d_type: true
Native Overlay Diff: true
userxattr: false
Logging Driver: json-file
Cgroup Driver: cgroupfs
Cgroup Version: 1
Plugins:
Volume: local
Network: bridge host ipvlan macvlan null overlay
Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog
Swarm: inactive
Runtimes: runc io.containerd.runc.v2 io.containerd.runtime.v1.linux
Default Runtime: runc
Init Binary: docker-init
containerd version: 10c12954828e7c7c9b6e0ea9b0c02b01407d3ae1
runc version: v1.1.2-0-ga916309
init version: de40ad0
Security Options:
seccomp
Profile: default
Kernel Version: 3.10.0-1160.el7.x86_64
Operating System: CentOS Linux 7 (Core)
OSType: linux
Architecture: x86_64
CPUs: 4
Total Memory: 7.622GiB
Name: docker-node
ID: ZWS6:7BS4:CRHX:AXGV:LSQ4:3JLD:AY7M:76IZ:YKSY:LAAC:PSTY:FTUA
Docker Root Dir: /var/lib/docker
Debug Mode: false
Registry: https://index.docker.io/v1/
Labels:
Experimental: false
Insecure Registries:
harbor.kubesphere.com:80
127.0.0.0/8
Registry Mirrors:
https://si7y70hh.mirror.aliyuncs.com/
Live Restore Enabled: false
~ docker --help
Usage: docker [OPTIONS] COMMAND
A self-sufficient runtime for containers
Options:
--config string Location of client config files (default "/root/.docker")
-c, --context string Name of the context to use to connect to the daemon (overrides DOCKER_HOST env var and
default context set with "docker context use")
-D, --debug Enable debug mode
-H, --host list Daemon socket(s) to connect to
-l, --log-level string Set the logging level ("debug"|"info"|"warn"|"error"|"fatal") (default "info")
--tls Use TLS; implied by --tlsverify
--tlscacert string Trust certs signed only by this CA (default "/root/.docker/ca.pem")
--tlscert string Path to TLS certificate file (default "/root/.docker/cert.pem")
--tlskey string Path to TLS key file (default "/root/.docker/key.pem")
--tlsverify Use TLS and verify the remote
-v, --version Print version information and quit
Management Commands:
app* Docker App (Docker Inc., v0.9.1-beta3)
builder Manage builds
buildx* Build with BuildKit (Docker Inc., v0.6.3-docker)
config Manage Docker configs
container Manage containers
context Manage contexts
image Manage images
manifest Manage Docker image manifests and manifest lists
network Manage networks
node Manage Swarm nodes
plugin Manage plugins
scan* Docker Scan (Docker Inc., v0.17.0)
secret Manage Docker secrets
service Manage services
stack Manage Docker stacks
swarm Manage Swarm
system Manage Docker
trust Manage trust on Docker images
volume Manage volumes
Commands:
attach Attach local standard input, output, and error streams to a running container
build Build an image from a Dockerfile
commit Create a new image from a container's changes
cp Copy files/folders between a container and the local filesystem
create Create a new container
diff Inspect changes to files or directories on a container's filesystem
events Get real time events from the server
exec Run a command in a running container
export Export a container's filesystem as a tar archive
history Show the history of an image
images List images
import Import the contents from a tarball to create a filesystem image
info Display system-wide information
inspect Return low-level information on Docker objects
kill Kill one or more running containers
load Load an image from a tar archive or STDIN
login Log in to a Docker registry
logout Log out from a Docker registry
logs Fetch the logs of a container
pause Pause all processes within one or more containers
port List port mappings or a specific mapping for the container
ps List containers
pull Pull an image or a repository from a registry
push Push an image or a repository to a registry
rename Rename a container
restart Restart one or more containers
rm Remove one or more containers
rmi Remove one or more images
run Run a command in a new container
save Save one or more images to a tar archive (streamed to STDOUT by default)
search Search the Docker Hub for images
start Start one or more stopped containers
stats Display a live stream of container(s) resource usage statistics
stop Stop one or more running containers
tag Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE
top Display the running processes of a container
unpause Unpause all processes within one or more containers
update Update configuration of one or more containers
version Show the Docker version information
wait Block until one or more containers stop, then print their exit codes
Run 'docker COMMAND --help' for more information on a command.
To get more help with docker, check out our guides at https://docs.docker.com/go/guides/
3.2 镜像命令
3.2.1 docker images
列出本地主机上的镜像
~ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest feb5d9fea6a5 10 months ago 13.3kB
# 各个选项的说明:
REPOSITORY:表示镜像的仓库源
TAG :镜像的标签
IMAGE ID :镜像ID
CREATED :镜像创建时间,指发布到镜像库中的时间,不是拉取时间。
SIZE :镜像大小
同一仓库源可以有多个TAG,代表这个仓库源的不同个版本,我们使用 REPOSITORY:TAG 来定义不同的镜像。如果你不指定一个镜像的版本标签,例如你只使用 Ubuntu,Docker 将默认使用 ubuntu:latest 镜像。默认的TAG的标签是 latest 的信息。
OPTIONS 说明:
:::color1
-a :列出本地所有的镜像(含中间映像层) -q :只显示镜像Image ID—digests :显示镜像的摘要信息
—no-trunc :显示完整的镜像信息
:::
3.2.2 docker search 某个XXX 镜像名字ID
- 网站
- 命令
docker search [OPTIONS] 镜像名字
:::color1 —no-trunc :显示完整的镜像描述
-s:列出收藏数不小于指定值的镜像。# 已经弃用
—automated :只列出automated build类型的镜像;
:::
~ docker search tomcat
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
tomcat Apache Tomcat is an open source implementati… 3372 [OK]
tomee Apache TomEE is an all-Apache Java EE certif… 97 [OK]
bitnami/tomcat Bitnami Tomcat Docker Image 46 [OK]
......
# --limit 最大搜索结果数(默认25)
~ docker search --limit 3 tomcat
# 指定收藏数在30以上的镜像
~ docker search -f stars=30 tomcat
或者
# 没有-s的用这个
~ docker search tomcat --filter=stars=30
# 搜索官方的镜像
~ docker search --filter is-official=true tomcat
3.2.3 docker pull 某个XXX 镜像名字ID
下载镜像
docker pull 镜像名字[:TAG]
~ docker search --limit 3 tomcat
~ docker pull tomcat # 等价于 docker pull tomcat:latest
# 拉取指定镜像的 tomcat
~ docker pull tomcat:8.5.41-alpine
3.2.4 docker rmi 某个XXX 镜像名字ID
删除镜像
删除单个
docker rmi -f <Image>:<Tag>
删除多个
# 删除指定的多个镜像名字
docker rmi -f <Image1>:<Tag> <Image2>:<Tag> ......
删除全部
docker rmi -f $(docker images -aq)
3.2.5 思考
结合我们Git的学习心得,大家猜猜是否会有 docker commit / docker push??
3.3 容器命令
有镜像才能创建容器,这是根本的前提(下载一个CentOS镜像演示)
~ docker pull centos:centos7.9.2009
~ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
centos centos7.9.2009 eeb6ee3f44bd 10 months ago 204MB
~ docker pull ubuntu:20.04
3.3.1 新建并启动容器
:::color1 docker run [OPTIONS] IMAGE [COMMAND] [ARG…]
Docker 里面套 Docker是好多架构的标准操作啦,比如说Jenkins Agent 用装了Docker的Docker image来实现自动化创建Docker Image
:::
OPTIONS:
:::color1 OPTIONS说明(常用):有些是一个减号,有些是两个减号
- —name=”容器新名字”:为容器指定一个名称;
- -d:后台运行容器,并返回容器ID,也即启动守护式容器;
- -i:以交互模式运行容器,通常与 -t 同时使用;
- -t:为容器重新分配一个伪输入终端,通常与 -i 同时使用;
- -P:随机端口映射;
- -p:指定端口映射,有以下四种格式
- ip:hostPort:containerPort
- ip::containerPort
- hostPort:containerPort
- containerPort
:::
启动交互式容器:
~ docker run -itd --name c1 --hostname c1 centos:centos7.9.2009 /bin/bash
~ docker exec -it c1 /bin/bash
[root@c1 /]# ls
anaconda-post.log bin dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
[root@c1 /]# cat /etc/redhat-release
CentOS Linux release 7.9.2009 (Core)
[root@c1 /]# hostname
c1
# 使用镜像centos:centos7.9.2009 以交互式模式启动一个容器,在容器内执行 /bin/bash 命令
docker run -it centos:centos7.9.2009 /bin/bash
3.3.2 列出当前所有正在运行的容器
:::color1 docker ps [OPTIONS]
:::
OPTIONS 说明:
:::color1
-a:列出当前所有正在运行的容器+历史上运行过的 -l:显示最近创建的容器。 -n:显示最近 n 个创建的容器。 -q:静默模式,只显示容器编号。—no-trunc:不截断输出。
:::
~ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
624bd36b61de centos:centos7.9.2009 "/bin/bash" 3 minutes ago Up 3 minutes c1
## 随机生成的名字不一般,格式是[一个形容词]_[名人或伟人的名字]
3.3.3 退出容器
两种退出方式:
exit:容器停止退出
Ctrl + P + Q:容器不停止退出
~ docker exec -it c1 /bin/bash
[root@c1 /]# exit
exit
# 容器不停止退出
~ docker exec -it c1 /bin/bash
[root@c1 /]# read escape sequence
# Ctrl + P + Q
3.3.4 启动容器
docker start 容器ID或者容器名
~ docker start c1
3.3.5 重启容器
docker restart 容器ID或者容器名
~ docker restart c1
3.3.6 停止容器
docker stop 容器ID或者容器名
# stop 温柔停止容器
~ docker stop c1
3.3.7 强制停止容器
docker kill 容器ID或者容器名
# kill 强制停止容器
~ docker kill c1
3.3.8 删除已停止的容器
docker rm 容器ID或者容器名
一次性删除多个容器
docker rm -f <Container1> <Container2> <Container3> ......
删除所有的容器
# 删除所有正在运行以及不再运行的容器
docker rm -f $(docker ps -aq)
或者
docker ps -qa | xargs docker rm -f
3.3.9 重要
3.3.9.1 启动守护式容器
使用镜像centos:latest以后台模式启动一个容器docker run -d centos
问题:然后docker ps -a进行查看,会发现容器已经退出。
很重要的要说明的一点:Docker容器后台运行,就必须有一个前台进程。
容器运行的命令如果不是那些一直挂起的命令(比如运行top,tail),就是会自动退出的。
这个是docker的机制问题,比如你的web容器,我们以nginx为例,正常情况下,我们配置启动服务只需要启动响应的service即可。例如:service nginx start。
但是,这样做,nginx为后台进程模式运行,就导致docker前台没有运行的应用,这样的容器后台启动后,会立即自杀因为他觉得他没事可做了。
所以,最佳的解决方案是,将你要运行的程序以前台进程的形式运行。
# 后台运行容器
~ docker run -it -d --name c1 centos:centos7.9.2009 /bin/bash
~ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e8bed136415e centos:centos7.9.2009 "/bin/bash" 2 minutes ago Up 2 minutes c1
3.3.9.2 查看容器日志
docker logs -f -t —tail 容器ID
:::color1 *-t:是加入时间戳
*-f:跟随最新的日志打印
*—tail 数字:显示最后多少条
:::
~ docker run -it -d --name c2 centos:centos7.9.2009 /bin/bash -c "while true;do echo hello,zzw;sleep 1;done"
~ docker ps -l
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
34f1e2fbd9b9 centos:centos7.9.2009 "/bin/bash -c 'while…" 12 seconds ago Up 12 seconds c2
# *-t:是加入时间戳
# *-f:跟随最新的日志打印
# *--tail 数字:显示最后多少条
~ docker logs -t -f --tail 5 c2
2022-08-07T09:02:59.591905262Z hello,zzw
2022-08-07T09:03:00.595619177Z hello,zzw
2022-08-07T09:03:01.598037828Z hello,zzw
3.3.9.3 查看容器内运行的进程
docker top 容器ID或者容器名字
~ docker top c3
UID PID PPID C STIME TTY TIME CMD
root 123503 123482 0 17:04 pts/0 00:00:00 /bin/bash -c while true;do echo hello,zzw;sleep 1;done
root 126047 123503 0 17:09 pts/0 00:00:00 sleep 1
3.3.9.4 查看容器内部细节
docker inspect 容器ID或者容器名字
docker inspect c3
3.3.9.5 进入正在运行的容器并以命令行交互
- docker exec -it 容器ID或者容器名字 bashShell
exec就是在container里执行后面的命令,如果执行的是开启新终端的命令就会开启新终端了。
/bin/bash 和 /bin/sh 都是开启终端的命令,相当于你在外面开启了container里面的终端,最后效果和你进container开终端是一样的。/bin/bash命令是打开新终端,打开新的终端实际上起作用的是用exec执行了/bin/bash,不是exec。
~ docker exec -it c1 /bin/bash
[root@e8bed136415e /]#
# 不进入到容器,直接在控制台显示想要的结果
~ docker exec -it c1 ls -l /tmp
total 12
-rw-r--r--. 1 root root 18 Aug 7 09:21 docker.txt
-rw-r--r--. 1 root root 16 Aug 7 09:19 host.txt
- 重新进入 docker attach 容器ID或者容器名字
~ docker attach c1
[root@e8bed136415e /]#
- 上述两个区别
:::color1
attach:直接进入容器启动命令的终端,不会启动新的进程 exec:是在容器中打开新的终端,并且可以启动新的进程:::
3.3.9.6 从容器内拷贝文件到主机上
docker cp 容器ID或者容器名称:容器内路径 目的主机路径
范例:
# 将宿主机的文件拷贝到容器中
~ echo "hello,from host" > host.txt
~ docker cp host.txt c1:/tmp
~ docker exec -it c1 /bin/bash
[root@e8bed136415e /]# cat /tmp/host.txt
hello,from host
[root@e8bed136415e /]# echo "hello,from docker" > /tmp/docker.txt
[root@e8bed136415e /]# exit
# 从容器中拷贝文件到宿主机
~ docker cp c1:/tmp/docker.txt /tmp
~ cat /tmp/docker.txt
hello,from docker
3.4 小总结
attach
Attach to a running container —- 当前Shell下attach连接指定运行容器build
Build an image from a Dockerfile —- 通过Dockerfile定制镜像commit
Create a new image from a container’s changes —- 提交当前容器为新的镜像cp
Copy files/folders from the containers filesystem to the host past —- 从容器中拷贝指定文件或者目录到宿主机中create
Create a new container —- 创建一个新的容器,同run,但是不启动容器diff
Inspect changes on a container’s filesystem —- 查看 docker 容器的变化events
Get real time events from the server —- 从 docker 服务获取容器实时事件exec
Run a command in a running container —- 在已存在的容器上运行命令export
Stream the contents of a container as a tar archive —- 导出容器的内容流作为一个 tar 归档文件[对应 import]history
Show the history of an image —- 展示一个镜像形成历史images
List images —- 列出本地系统当前镜像info
Display system-wide information —- 显示系统相关信息inspect
Return low-level information on Docker objects —- 查看容器详细信息kill
Kill a runnning containers —- kill 指定 docker 容器load
Load an image from a tar archive —- 从一个 tar 包中加载一个镜像 [ 对应 save ]login
Log in to a Docker registry —- 注册或者登陆一个 docker 源服务器logout
Log out from a Docker registry —- 从当前 Docker Registry 退出logs
Fetch the logs of a container —- 输出当前容器日志信息port
List port mappings or a specific mapping for the container —- 查看映射端口对应的容器内部源端口pause
Pause all processes within one or more containers —- 暂停容器ps
List containers —- 列出容器列表pull
Pull an image or a repository from a registry —- 从docker镜像源服务器拉取指定镜像或者库镜像push
Push an image or a repository to a registry —- 推送指定镜像或者库镜像至docker镜像源服务器restart
Restart one or more containers —- 重启运行的容器rm
Remove one or more containers —- 移除一个或者多个容器rmi
Remove one or more images —- 移除一个或者多个镜像[无容器使用该镜像才可输出,否则需要输出相关容器才能可以继续或者 -f 强制删除]run
Run a command in a new container —- 创建一个新的容器并运行一个命令save
Save one or more images to a tar archive —- 保存一个镜像为一个 tar 包[ 对应 load ]search
Search the Docker Hub for images —- 在 DockerHub 中搜索镜像start
Start one or more stopped containers —- 启动容器stop
Stop one or more running containers —- 停止容器stats
Display a live stream of container(s) resource usage statistics —- 显示容器资源使用统计的实时流tag
Tag an image into a repository —- 给源中镜像打标签top
Display the running processes of a container —- 查看容器中运行的进程信息unpause
Unpause a pause container —- 取消暂停容器version
Show the Docker version information —- 查看 Docker 版本号wait
Block until one or more containers stop, then print their exit codes —- 截取容器停止时的退出状态值
4 Docker 镜像
docker commit 将容器提交成镜像
- docker export 将容器打包成 tar 包
docker export
-o .tar 根据容器的大小,打包的效率也会随之变化
- docker import 将 tar 包提交为镜像
docker import
.tar : 根据Tar包的大小,提交镜像的效率也会随之变化
- docker save 将镜像打包成 tar 包
docker save
: -o .tar 根据镜像的大小,打包的效率也会随之变化
- docker load 将 tar 包提交为镜像
docker load -i
.tar 根据Tar包的大小,提交镜像的效率也会随之变化
4.1 Docker 镜像是什么
镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需的所有内容,包括代码、运行时、库、环境变量和配置文件。
4.1.1 UnionFS(联合文件系统)
UnionFS(联合文件系统):Union文件系统(UnionFS)是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层一层的叠加
,同时可以将不同目录挂载到同一个虚拟文件系统下(Unite several directories into a single virtual filesystem)。Union文件系统是Docker镜像的基础。<font style="color:#E8323C;">镜像可以通过分层来进行继承</font>
,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。
特性:一次同时加载多个文件系统,但是从外面看起来,只能看到一个文件系统,<font style="color:#E8323C;">联合加载会把各种文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录</font>。
联合文件系统:分层,轻量,并且能够聚合的一种镜像基础。
4.1.2 Docker 镜像加载原理
Docker 镜像加载原理:
Docker 的镜像实际上是由一层一层的文件系统组成
的,这种层级的文件系统UnionFS。
<font style="color:#E8323C;">在Docker 镜像的最底层时引导文件系统 bootfs</font>
。这一层与我们典型的Linux/Unix系统是一样的,包含 boot加载器和内核。当 boot 加载完成之后整个内核都在内存中,此时内存的使用权已由 bootfs 转交给内核,此时系统也会卸载 bootfs。
rootfs(root file system),在 bootfs 之上,包含的就是典型 Linux 系统中的 /dev,/proc,/bin,/etc等标准目录和文件。rootfs 就是各种不同的操作系统发行版
,比如 Ubuntu,CentOS 等等。
![💎3 [尚硅谷-Docker] Docker迅速入门丨零基础学Docker - 图18](/uploads/projects/seekerzw@yaaygq/01baed10b867a454b8a85914771a58d7.png)
![💎3 [尚硅谷-Docker] Docker迅速入门丨零基础学Docker - 图19](/uploads/projects/seekerzw@yaaygq/c2d7f9b502a09bd32f6ab87cd730e75b.png)
![💎3 [尚硅谷-Docker] Docker迅速入门丨零基础学Docker - 图20](/uploads/projects/seekerzw@yaaygq/cd6369e697ea625b132c98810738230c.png)
bash
docker run -it -d --name u1 ubuntu /bin/bash
docker run -it -d --name c1 centos:centos7.9.2009 /bin/bash
# 查看各容器的内核版本
~ docker exec -it u1 uname -r
3.10.0-1160.el7.x86_64
~ docker exec -it c1 uname -r
3.10.0-1160.el7.x86_64
### 4.1.3 分层的镜像

![💎3 [尚硅谷-Docker] Docker迅速入门丨零基础学Docker - 图22](/uploads/projects/seekerzw@yaaygq/7b00f50bdb2de6d358667271ea22dc2b.png)
bash
~ docker pull tomcat:8.0.53
~ docker images tomcat:8.0.53
REPOSITORY TAG IMAGE ID CREATED SIZE
tomcat 8.0.53 ef6a7c98d192 3 years ago 356MB
# Tomcat 镜像是基础操作系统+JDK+Tomcat构建成的。包含Tomcat应用的所有环境
### 4.1.4 为什么Docker镜像要采用这种分层结构呢?
Docker 镜像分层最大的一个好处就是共享资源,方便复制迁移,就是为了**<font style="color:#E8323C;">复用</font>**
。
比如说有多个镜像都从相同的 base 镜像构建而来,那么 Docker Host 只需在磁盘上保存一份 base 镜像;
同时内存中也只需加载一份 base 镜像,就可以为所有容器服务了。而且镜像的每一层都可以被共享。
4.2 Docker 镜像特点
<font style="color:#E8323C;">Docker 镜像层都是只读的,容器层是可写的。</font>
当容器启动时,一个新的可写层被加载到镜像的顶部。这一层通常被称为“容器层”,“容器层”之下的都叫镜像层。
所有对容器的改动,无论添加、删除、还是修改文件都只会发生在容器中。只有容器层时可写的,容器层下面的所有镜像层都是只读的。
4.3 Docker 镜像 commit 操作补充
:::color1 $ docker commit 提交容器副本使之成为一个新的进行
$ docker commit -m=”提交的描述信息” -a=”作者” 容器ID 要创建的目标镜像名:[标签名]:::
范例:演示 Tomcat 模板
- 从 Hub 上下载 tomcat 镜像到本地并成功运行
- 故意删除上一步镜像生产 tomcat 的文档
- 也即当前的 tomcat 运行实例是一个没有文档内容的容器,以它为模板 commit 一个没有 doc 的 tomcat 新镜像 ks/tomcat
- 启动我们的新镜像并和原来的对比
# 使用指定端口
$ docker pull tomcat:8.0.53
# -p 主机端口:docker容器端口(端口映射)
# -P 随机分配主机端口
# -i 交互 -t 创建伪终端
# -d 后台运行容器
$ docker run -it -p 8080:8080 --name t1 tomcat:8.0.53
$ curl localhost:8080
可以展示Tomcat 的页面
# tomcat 8版本之后的路径404是因为新版本tomcat docker 目录换了一下,webapps下没有主页,
# 在webapps.dlist下,把webapps.dlist下的文件移到webaps下就好了
# 使用随机端口
$ docker run -it -P -d --name t2 tomcat:8.0.53
$ docker ps -l
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
31d488831d03 tomcat:8.0.53 "catalina.sh run" 4 seconds ago Up 3 seconds 0.0.0.0:49154->8080/tcp, :::49154->8080/tcp t2
$ curl localhost:49154
可以展示Tomcat 的页面
~ docker exec -it t1 /bin/bash
root@166ff986d06b:/usr/local/tomcat# cd webapps/
root@166ff986d06b:/usr/local/tomcat/webapps# ls -l
total 8
drwxr-xr-x. 3 root root 4096 Sep 12 2018 ROOT
drwxr-xr-x. 14 root root 4096 Sep 12 2018 docs
drwxr-xr-x. 6 root root 83 Sep 12 2018 examples
drwxr-xr-x. 5 root root 87 Sep 12 2018 host-manager
drwxr-xr-x. 5 root root 103 Sep 12 2018 manager
root@166ff986d06b:/usr/local/tomcat/webapps# rm -rf docs/
root@166ff986d06b:/usr/local/tomcat/webapps# ls -l
total 4
drwxr-xr-x. 3 root root 4096 Sep 12 2018 ROOT
drwxr-xr-x. 6 root root 83 Sep 12 2018 examples
drwxr-xr-x. 5 root root 87 Sep 12 2018 host-manager
drwxr-xr-x. 5 root root 103 Sep 12 2018 manager
~ docker commit -a "zhongzhiwei <zhongzhiwei@kubesphere.io>" -m "将Tomcat的Docs删除" t1 ks/tomcat:1.0
~ docker images ks/tomcat:1.0
REPOSITORY TAG IMAGE ID CREATED SIZE
ks/tomcat 1.0 f970d1ac7724 10 seconds ago 356MB
# 查看 ks/tomcat:1.0 的镜像的历史记录
~ docker image history ks/tomcat:1.0
IMAGE CREATED CREATED BY SIZE COMMENT
f970d1ac7724 26 seconds ago catalina.sh run 88.9kB 将Tomcat的Docs删除
...省略其他Tomcat镜像历史记录...
# 启动我们的新镜像并和原来的对比
~ docker run -it -d -P --name kst1 ks/tomcat:1.0
~ docker ps -l
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f134ddc6149d ks/tomcat:1.0 "catalina.sh run" 5 seconds ago Up 3 seconds 0.0.0.0:49155->8080/tcp, :::49155->8080/tcp kst1
:::color1 官方的Tomcat镜像是完整的功能,自定义的Tomcat镜像是缺少 Docs 的文档功能。
:::
范例:演示 Ubuntu 安装 vim
- 从 Hub 上下载 Ubuntu 镜像到本地并成功运行
- 原始的默认ubuntu镜像是不带着 vim 命令的
- 外网连通的情况下,安装 vim
- 安装完成后,commit 成新的镜像
- 启动新镜像生成容器实例并和原来的对比
$ docker pull ubuntu
$ docker run -it --name u1 -d ubuntu /bin/bash
# 更新容器的包管理工具
root@d674ed1c5c08:/# apt update -y
# 安装 vim 软件
root@d674ed1c5c08:/# apt install -y vim
root@d674ed1c5c08:/# vim --version
VIM - Vi IMproved 8.1 (2018 May 18, compiled Nov 08 2021 14:21:34)
root@d674ed1c5c08:/# exit
# 将容器提交为镜像
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d674ed1c5c08 ubuntu "/bin/bash" 17 minutes ago Up 17 minutes u1
$ docker commit -m "添加vim软件" -a 'zhongzhiwei <935523993@qq.com>' u1 myubuntu:v1.0
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
myubuntu v1.0 3a28444435e6 4 seconds ago 174MB
ubuntu latest ba6acccedd29 2 months ago 72.8MB
$ docker run -it --name mu1 -d myubuntu:v1.0 /bin/bash
$ docker exec -it mu1 /bin/bash
root@d674ed1c5c08:/# vim --version
VIM - Vi IMproved 8.1 (2018 May 18, compiled Nov 08 2021 14:21:34)
root@d674ed1c5c08:/# exit
# 查看镜像历史
$ docker history ubuntu
IMAGE CREATED CREATED BY SIZE COMMENT
ba6acccedd29 2 months ago /bin/sh -c #(nop) CMD ["bash"] 0B
<missing> 2 months ago /bin/sh -c #(nop) ADD file:5d68d27cc15a80653… 72.8MB
$ docker history myubuntu:v1.0
IMAGE CREATED CREATED BY SIZE COMMENT
3a28444435e6 8 minutes ago /bin/bash 101MB 添加vim软件
ba6acccedd29 2 months ago /bin/sh -c #(nop) CMD ["bash"] 0B
<missing> 2 months ago /bin/sh -c #(nop) ADD file:5d68d27cc15a80653… 72.8MB
小总结
Docker 中的镜像分层,支持通过扩展现有镜像,创建新的镜像。类似于 Java 继承于一个 Base 基础类,自己按需扩展。新镜像是从 Base 镜像一层一层叠加生成的。每安装一个软件,就在现有镜像的基础上增加一层。
:::color1
commit:将运行的容器直接提交为镜像。 export:将容器(运行或不运行)打包成tar包,再由import将tar包提交为镜像。 save:将镜像打包成tar包,再有load将tar包提交为镜像。:::
作业:案例 CentOS + Ubuntu 系统再官方镜像中添加 vim 软件并提交镜像运行成容器测试
~ docker run -itd --name c1 centos /bin/bash
~ docker exec -it c1 /bin/bash
$ rm -rf /etc/yum.repos.d/CentOS-Linux-*
$ curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-vault-8.5.2111.repo
$ yum update ; yum install -y vim ; yum clean all
$ vim --version
VIM - Vi IMproved 8.0 (2016 Sep 12, compiled Sep 22 2021 11:10:49)
$ exit
~ docker commit -a "zhongzhiwei <935523993@qq.com>" -m "添加VIM软件" c1 kubesphere-centos:1.0
~ docker images kubesphere-centos:1.0
REPOSITORY TAG IMAGE ID CREATED SIZE
kubesphere-centos 1.0 7f36413d0ef3 4 seconds ago 271MB
# 运行添加VIM的新镜像
~ docker run -it --name kc1 kubesphere-centos:1.0 /bin/bash
$ vim --version
VIM - Vi IMproved 8.0 (2016 Sep 12, compiled Sep 22 2021 11:10:49)
###
~ docker run -itd --name u1 ubuntu /bin/bash
~ docker exec -it u1 /bin/bash
$ apt update ; apt install -y vim
$ vim --version
VIM - Vi IMproved 8.0 (2016 Sep 12, compiled Sep 22 2021 11:10:49)
$ exit
~ docker commit -a "zhongzhiwei <935523993@qq.com>" -m "添加VIM软件" c1 kubesphere-ubuntu:1.0
~ docker images kubesphere-ubuntu:1.0
REPOSITORY TAG IMAGE ID CREATED SIZE
kubesphere-ubuntu 1.0 7f36413d0ef3 4 seconds ago 178MB
# 运行添加VIM的新镜像
~ docker run -it --name ku1 kubesphere-ubuntu:1.0 /bin/bash
$ vim --version
VIM - Vi IMproved 8.0 (2016 Sep 12, compiled Sep 22 2021 11:10:49)
5 Docker 容器数据卷
5.1 Docker 容器数据卷是什么
先来看看Docker的理念:
*将运用与运行的环境打包形成容器运行,运行可以伴随着容器,但是我们对数据的要求希望是持久化的
*容器之间希望有可能共享数据 Docker容器产生的数据,如果不通过 docker commit 生成新的镜像,使得数据做为镜像的一部分保存下来,那么当容器删除后,数据自然也就没有了。为了能保存数据在 Docker 中我们使用容器数据卷。
一句话:类似于Redis的RDB文件和AOF文件
将Docker容器内的数据保存进宿主机的磁盘中
运行一个带有容器卷存储功能的容器实例
$ docker run -it --privileged=true -v /宿主机绝对路径:/容器内目录 镜像名
5.2 Docker 容器数据卷能干嘛
:::color1 数据卷就是目录或者文件,存在于一个或者多个容器中,由Docker挂载到容器,但是不属于联合文件系统,因此能够绕过 Union File System 提供一些用于持续存储或者共享数据的特性:
卷的设计目的就是数据持久化,完全独立于容器的生存周期,因此Docker不会在容器删除时删除其挂载的数据卷。Docker 容器(数据) —-容器数据卷方式完成数据的持久化重要资料backup—> 映射,容器内的数据备份+持久化到本地主机目录
:::
- 将运用与运行的环境打包镜像,run 后形成容器实例运行,但是我们对数据的要求希望是持久化的
- Docker 容器产生的数据,如果不备份,那么当容器实例删除后,容器内的数据自然也就没有了
- 为了能保存数据在Docker中我们使用数据卷
- 特点:
- 数据据可以在容器之间共享或者重用数据
- 卷中的更改可以直接实时生效(跟 docker cp 比较)
- 数据卷中的更改不会包含在镜像的更新中
- 数据卷的生命周期一直持续到没有容器使用它为止
:::color1
- 容器的持久化
- 容器间的继承 + 共享数据
:::
5.3 数据卷
容器内添加数据卷
- 直接命令添加数据卷
- 命令
:::color1 docker run -it -v /宿主机绝对路径目录:/容器内的目录 镜像名
:::
范例:
# 数据卷会自动创建
~ docker run -itd \
-v /myDataVolume:/dataVolumeContainer centos:centos7.9.2009 /bin/bash
~ ls -ld /myDataVolume/
drwxr-xr-x. 2 root root 6 Aug 7 20:42 /myDataVolume/
# 查看容器的数据卷
~ docker ps -l
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
cd4098a4c4a1 centos:centos7.9.2009 "/bin/bash" About a minute ago Up About a minute trusting_brattain
~ docker exec -it trusting_brattain /bin/bash
[root@cd4098a4c4a1 /]# ls -ld /dataVolumeContainer/
drwxr-xr-x. 2 root root 6 Aug 7 12:42 /dataVolumeContainer/
- 查看数据卷是否挂载成功
~ docker inspect trusting_brattain | grep -A 9 "Mounts"
"Mounts": [
{
"Type": "bind",
"Source": "/myDataVolume",
"Destination": "/dataVolumeContainer",
"Mode": "",
"RW": true,
"Propagation": "rprivate"
}
],
- 容器和宿主机之间数据共享
~ docker exec -it trusting_brattain /bin/bash
[root@cd4098a4c4a1 /]# cat /dataVolumeContainer/host.txt
From Host data
[root@cd4098a4c4a1 /]# echo "Hello Container data" >> /dataVolumeContainer/host.txt
[root@cd4098a4c4a1 /]# exit
- 容器退出后,主机修改后数据是否同步
~ cat /myDataVolume/host.txt
From Host data
Hello Container data
# 1.容器先停止退出
# 2.主机修改 a.log
# 3.容器重启进入
# 4.查看主机修改过的a.log
# 内容同步
- 命令(带权限)
:::color1 docker run -it -v /宿主机绝对路径目录:/容器内的目录:ro 镜像名
:::
范例:
~ docker run -it -d --name centos-demo \
-v /myHostVolume:/dataVolumeContainer:ro centos:centos7.9.2009 /bin/bash
~ echo "From Host Data" > /myHostVolume/host.txt
# 查看容器的数据卷信息
~ docker exec -it centos-demo /bin/bash
[root@5dfd7423052b /]# cat /dataVolumeContainer/host.txt
From Host Data
[root@5dfd7423052b /]# echo "From Docker data" >> /dataVolumeContainer/host.txt
bash: /dataVolumeContainer/host.txt: Read-only file system
[root@5dfd7423052b /]# touch /dataVolumeContainer/docker.txt
touch: cannot touch '/dataVolumeContainer/docker.txt': Read-only file system
# 发现在容器中的数据卷只能是只读功能,没有写入操作。
~ docker inspect centos-demo | grep -A 3 HostConfig
"HostConfig": {
"Binds": [
"/myHostVolume:/dataVolumeContainer:ro"
],
- Dockerfile 添加数据卷
:::warning
参考 tomcat 8 的 dockerfile 入门 —> https://github.com/docker-library/tomcat DockerHub 使用 docker run 运行的镜像,进行反解析之后就是 Dockerfile :::dockerfile
# https://github.com/docker-library/tomcat/blob/master/10.0/jdk8/corretto-al2/Dockerfile
#
# NOTE: THIS DOCKERFILE IS GENERATED VIA "apply-templates.sh"
#
# PLEASE DO NOT EDIT IT DIRECTLY.
#
FROM amazoncorretto:8-al2-jdk
ENV CATALINA_HOME /usr/local/tomcat
ENV PATH $CATALINA_HOME/bin:$PATH
RUN mkdir -p "$CATALINA_HOME"
WORKDIR $CATALINA_HOME
# let "Tomcat Native" live somewhere isolated
ENV TOMCAT_NATIVE_LIBDIR $CATALINA_HOME/native-jni-lib
ENV LD_LIBRARY_PATH ${LD_LIBRARY_PATH:+$LD_LIBRARY_PATH:}$TOMCAT_NATIVE_LIBDIR
# see https://www.apache.org/dist/tomcat/tomcat-10/KEYS
# see also "versions.sh" (https://github.com/docker-library/tomcat/blob/master/versions.sh)
ENV GPG_KEYS A9C5DF4D22E99998D9875A5110C01C5A2F6059E7
ENV TOMCAT_MAJOR 10
ENV TOMCAT_VERSION 10.0.23
ENV TOMCAT_SHA512 0e0263e8280f2ccfb4bef916444a6105fef689a3d95c334c8a7bfe59f1e3966d48ea624727f1818a4df331a603f1ac5e21b908dda3cae676ddc1aef90c2d12ab
RUN set -eux; \
\
# http://yum.baseurl.org/wiki/YumDB.html
if ! command -v yumdb > /dev/null; then \
yum install -y --setopt=skip_missing_names_on_install=False yum-utils; \
yumdb set reason dep yum-utils; \
fi; \
# a helper function to "yum install" things, but only if they aren't installed (and to set their "reason" to "dep" so "yum autoremove" can purge them for us)
_yum_install_temporary() { ( set -eu +x; \
local pkg todo=''; \
for pkg; do \
if ! rpm --query "$pkg" > /dev/null 2>&1; then \
todo="$todo $pkg"; \
fi; \
done; \
if [ -n "$todo" ]; then \
set -x; \
yum install -y --setopt=skip_missing_names_on_install=False $todo; \
yumdb set reason dep $todo; \
fi; \
) }; \
_yum_install_temporary gzip tar; \
\
ddist() { \
local f="$1"; shift; \
local distFile="$1"; shift; \
local mvnFile="${1:-}"; \
local success=; \
local distUrl=; \
for distUrl in \
# https://issues.apache.org/jira/browse/INFRA-8753?focusedCommentId=14735394#comment-14735394
"https://www.apache.org/dyn/closer.cgi?action=download&filename=$distFile" \
# if the version is outdated (or we're grabbing the .asc file), we might have to pull from the dist/archive :/
"https://downloads.apache.org/$distFile" \
"https://www-us.apache.org/dist/$distFile" \
"https://www.apache.org/dist/$distFile" \
"https://archive.apache.org/dist/$distFile" \
# if all else fails, let's try Maven (https://www.mail-archive.com/users@tomcat.apache.org/msg134940.html; https://mvnrepository.com/artifact/org.apache.tomcat/tomcat; https://repo1.maven.org/maven2/org/apache/tomcat/tomcat/)
${mvnFile:+"https://repo1.maven.org/maven2/org/apache/tomcat/tomcat/$mvnFile"} \
; do \
if curl -fL -o "$f" "$distUrl" && [ -s "$f" ]; then \
success=1; \
break; \
fi; \
done; \
[ -n "$success" ]; \
}; \
\
ddist 'tomcat.tar.gz' "tomcat/tomcat-$TOMCAT_MAJOR/v$TOMCAT_VERSION/bin/apache-tomcat-$TOMCAT_VERSION.tar.gz" "$TOMCAT_VERSION/tomcat-$TOMCAT_VERSION.tar.gz"; \
echo "$TOMCAT_SHA512 *tomcat.tar.gz" | sha512sum --strict --check -; \
ddist 'tomcat.tar.gz.asc' "tomcat/tomcat-$TOMCAT_MAJOR/v$TOMCAT_VERSION/bin/apache-tomcat-$TOMCAT_VERSION.tar.gz.asc" "$TOMCAT_VERSION/tomcat-$TOMCAT_VERSION.tar.gz.asc"; \
export GNUPGHOME="$(mktemp -d)"; \
for key in $GPG_KEYS; do \
gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key"; \
done; \
gpg --batch --verify tomcat.tar.gz.asc tomcat.tar.gz; \
tar -xf tomcat.tar.gz --strip-components=1; \
rm bin/*.bat; \
rm tomcat.tar.gz*; \
command -v gpgconf && gpgconf --kill all || :; \
rm -rf "$GNUPGHOME"; \
\
# https://tomcat.apache.org/tomcat-9.0-doc/security-howto.html#Default_web_applications
mv webapps webapps.dist; \
mkdir webapps; \
# we don't delete them completely because they're frankly a pain to get back for users who do want them, and they're generally tiny (~7MB)
\
nativeBuildDir="$(mktemp -d)"; \
tar -xf bin/tomcat-native.tar.gz -C "$nativeBuildDir" --strip-components=1; \
_yum_install_temporary \
apr-devel \
gcc \
make \
openssl11-devel \
; \
( \
export CATALINA_HOME="$PWD"; \
cd "$nativeBuildDir/native"; \
aprConfig="$(command -v apr-1-config)"; \
./configure \
--libdir="$TOMCAT_NATIVE_LIBDIR" \
--prefix="$CATALINA_HOME" \
--with-apr="$aprConfig" \
--with-java-home="$JAVA_HOME" \
--with-ssl \
; \
nproc="$(nproc)"; \
make -j "$nproc"; \
make install; \
); \
rm -rf "$nativeBuildDir"; \
rm bin/tomcat-native.tar.gz; \
\
# mark any explicit dependencies as manually installed
find "$TOMCAT_NATIVE_LIBDIR" -type f -executable -exec ldd '{}' ';' \
| awk '/=>/ && $(NF-1) != "=>" { print $(NF-1) }' \
| xargs -rt readlink -e \
| sort -u \
| xargs -rt rpm --query --whatprovides \
| sort -u \
| tee "$TOMCAT_NATIVE_LIBDIR/.dependencies.txt" \
| xargs -r yumdb set reason user \
; \
\
# clean up anything added temporarily and not later marked as necessary
yum autoremove -y; \
yum clean all; \
rm -rf /var/cache/yum; \
\
# sh removes env vars it doesn't support (ones with periods)
# https://github.com/docker-library/tomcat/issues/77
find ./bin/ -name '*.sh' -exec sed -ri 's|^#!/bin/sh$|#!/usr/bin/env bash|' '{}' +; \
\
# fix permissions (especially for running as non-root)
# https://github.com/docker-library/tomcat/issues/35
chmod -R +rX .; \
chmod 777 logs temp work; \
\
# smoke test
catalina.sh version
# verify Tomcat Native is working properly
RUN set -eux; \
nativeLines="$(catalina.sh configtest 2>&1)"; \
nativeLines="$(echo "$nativeLines" | grep 'Apache Tomcat Native')"; \
nativeLines="$(echo "$nativeLines" | sort -u)"; \
if ! echo "$nativeLines" | grep -E 'INFO: Loaded( APR based)? Apache Tomcat Native library' >&2; then \
echo >&2 "$nativeLines"; \
exit 1; \
fi
EXPOSE 8080
CMD ["catalina.sh", "run"]
范例:Docker 容器数据卷
1. 根目录下新建 mydocker 文件夹并进入
2. 可在 Dockerfile 中使用 VOLUME 指令来给镜像添加一个或者多个数据卷
:::color1
VOLUME[“/dataVolumeContainer1” ,”/dataVolumeContainer2” ,”/dataVolumeContainer3”]
说明:
出于可移植和分享的考虑,用 -v 主机目录:容器目录 这种方法不能够直接在Dockerfile中实现。
由于宿主机目录是依赖于特定宿主机的,并不能够保证在所有的宿主机上都存在这样的特定目录。
:::
- File 构建
- build 后生成镜像 -> 获得一个新镜像 ks/centos:1.0
- run 容器
- 通过上述步骤,容器内的卷目录地址已经知道对应的主机目录地址了吗?
- 主机对应默认地址
$ mkdir -pv /mydocker ; cd /mydocker
$ cat > Dockerfile <<EOF
# 设置基础镜像
FROM centos:centos7.9.2009
# 设置容器的数据卷挂载,Docker会在宿主机开辟一块空间用于数据卷的持久化
VOLUME ["/dataVolumeContainer1", "/dataVolumeContainer2"]
# 打印文本信息
CMD echo "Finished, ------> Success"
# 容器的启动运行程序
CMD /bin/bash
EOF
# build 后生成镜像 -> 获得一个新镜像 ks/centos:1.0
$ docker build -f /mydocker/Dockerfile -t ks/centos:1.0 .
Sending build context to Docker daemon 2.048kB
Step 1/4 : FROM centos:centos7.9.2009
---> eeb6ee3f44bd
Step 2/4 : VOLUME ["/dataVolumeContainer1", "/dataVolumeContainer2"]
---> Running in 8669a671d710
Removing intermediate container 8669a671d710
---> 4217584674d3
Step 3/4 : CMD echo "Finished, ------> Success"
---> Running in e70c9faf7633
Removing intermediate container e70c9faf7633
---> a5b7fa2c931a
Step 4/4 : CMD /bin/bash
---> Running in 717a1acf0aed
Removing intermediate container 717a1acf0aed
---> da4deaafa2b2
Successfully built da4deaafa2b2
Successfully tagged ks/centos:1.0
# 查看镜像
$ docker images ks/centos:1.0
REPOSITORY TAG IMAGE ID CREATED SIZE
ks/centos 1.0 da4deaafa2b2 57 minutes ago 204MB
# 运行容器
$ docker run -it --name ks1 ks/centos:1.0 /bin/bash
[root@9bc6e66cb278 /]# ls -l /dataVolumeContainer*
/dataVolumeContainer1:
total 0
/dataVolumeContainer2:
total 0
[root@9bc6e66cb278 /]# echo "Hello dataVolumeContainer1 Data" > /dataVolumeContainer1/container1.txt
[root@9bc6e66cb278 /]# echo "Hello dataVolumeContainer2 Data" > /dataVolumeContainer2/container2.txt
# 容器的数据卷要与宿主机进行数据的交互沟通
# 查看容器的数据卷的挂载路径
$ docker inspect ks1 | grep -A 21 "Mounts"
"Mounts": [
{
"Type": "volume",
"Name": "b21f926635e0cd0b8586b01eec96b46cff36eaa12b9461ce24b5aae39917948b",
"Source": "/var/lib/docker/volumes/b21f926635e0cd0b8586b01eec96b46cff36eaa12b9461ce24b5aae39917948b/_data",
"Destination": "/dataVolumeContainer1",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
},
{
"Type": "volume",
"Name": "54327544d13290a1630b6bb138c47383f0515e55932aaff6b814fc813ceafd27",
"Source": "/var/lib/docker/volumes/54327544d13290a1630b6bb138c47383f0515e55932aaff6b814fc813ceafd27/_data",
"Destination": "/dataVolumeContainer2",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
}
],
$ ls -l /var/lib/docker/volumes/b21f926635e0cd0b8586b01eec96b46cff36eaa12b9461ce24b5aae39917948b/_data
total 4
-rw-r--r--. 1 root root 32 Aug 7 22:46 container1.txt
$ ls -l /var/lib/docker/volumes/54327544d13290a1630b6bb138c47383f0515e55932aaff6b814fc813ceafd27/_data
total 4
-rw-r--r--. 1 root root 32 Aug 7 22:47 container2.txt
$ cat /var/lib/docker/volumes/b21f926635e0cd0b8586b01eec96b46cff36eaa12b9461ce24b5aae39917948b/_data/container1.txt
Hello dataVolumeContainer1 Data
$ cat /var/lib/docker/volumes/54327544d13290a1630b6bb138c47383f0515e55932aaff6b814fc813ceafd27/_data/container2.txt
Hello dataVolumeContainer2 Data
- 备注
Docker 挂载主机目录Docker访问出现 cannot open directory .: Permission denied。
解决办法:在挂载目录后多加一个 —privileged=true 参数即可
5.4 数据卷容器
5.4.1 数据卷容器是什么
命名的容器挂载数据卷,其它容器通过挂载这个(父容器)实现数据共享,挂载数据卷的容器,称之为数据卷容器。
活动硬盘上面挂载活动硬盘,实现数据的传递依赖。
5.4.2 数据卷容器总体介绍
以上一步新建的镜像zzyy/centos为模板并运行容器 dc01 / dco2 / dc03
它们已经具有容器卷
- /dataVolumeContainer1
- /dataVolumeContainer2
5.4.3 容器间传递共享(—volumes-from)
先启动一个父容器 dc01
~ docker images ks/centos:1.0
REPOSITORY TAG IMAGE ID CREATED SIZE
ks/centos 1.0 da4deaafa2b2 3 hours ago 204MB
~ docker run -it --name dc01 ks/centos:1.0
[root@04629a777bbc /]# touch /dataVolumeContainer2/dc01_add.txt
[root@04629a777bbc /]# ls -l /dataVolumeContainer*
/dataVolumeContainer1:
total 0
/dataVolumeContainer2:
total 0
-rw-r--r--. 1 root root 0 Aug 7 16:43 dc01_add.txt
dc02 / dc03 继承自 dc01
- —volumes-from
- 命令
- dc02/ dc03 分别在 /dataVolumeContainer2 各自新增内容
~ docker run -it --name dc02 --volumes-from dc01 ks/centos:1.0
[root@0e1fb0e5dda8 /]# ls -l /dataVolumeContainer2/
total 0
-rw-r--r--. 1 root root 0 Aug 7 16:43 dc01_add.txt
[root@0e1fb0e5dda8 /]# touch /dataVolumeContainer2/dc02_add.txt
~ docker run -it --name dc03 --volumes-from dc01 ks/centos:1.0
[root@628252b6bbee /]# ls -l /dataVolumeContainer2/
total 0
-rw-r--r--. 1 root root 0 Aug 7 16:43 dc01_add.txt
-rw-r--r--. 1 root root 0 Aug 7 16:47 dc02_add.txt
[root@628252b6bbee /]# touch /dataVolumeContainer2/dc03_add.txt
回到dc01可以看到 dc02 / dc03各自添加的都能共享了
~ docker exec -it dc01 /bin/bash
[root@04629a777bbc /]# ls -l /dataVolumeContainer2/
total 0
-rw-r--r--. 1 root root 0 Aug 7 16:43 dc01_add.txt
-rw-r--r--. 1 root root 0 Aug 7 16:47 dc02_add.txt
-rw-r--r--. 1 root root 0 Aug 7 16:47 dc03_add.txt
删除dc01,dc02修改后dc03可否访问
~ docker rm -f dc01
~ docker exec -it dc02 /bin/bash
[root@0e1fb0e5dda8 /]# ls -l /dataVolumeContainer2/
total 0
-rw-r--r--. 1 root root 0 Aug 7 16:43 dc01_add.txt
-rw-r--r--. 1 root root 0 Aug 7 16:47 dc02_add.txt
-rw-r--r--. 1 root root 0 Aug 7 16:47 dc03_add.txt
[root@0e1fb0e5dda8 /]# touch /dataVolumeContainer2/dc02_update.txt
~ docker attach dc03
[root@628252b6bbee /]# ls -l /dataVolumeContainer2/
total 0
-rw-r--r--. 1 root root 0 Aug 7 16:43 dc01_add.txt
-rw-r--r--. 1 root root 0 Aug 7 16:47 dc02_add.txt
-rw-r--r--. 1 root root 0 Aug 7 16:52 dc02_update.txt
-rw-r--r--. 1 root root 0 Aug 7 16:47 dc03_add.txt
# --volumes-from 虽然指定容器数据卷,但是其实是宿主机的一片存储区域
删除dc02 后 dc03 可否访问
~ docker rm -f dc02
~ docker exec -it dc03 /bin/bash
[root@628252b6bbee /]# touch /dataVolumeContainer2/dc03_update.txt
[root@628252b6bbee /]# ls -l /dataVolumeContainer2/
total 0
-rw-r--r--. 1 root root 0 Aug 7 16:43 dc01_add.txt
-rw-r--r--. 1 root root 0 Aug 7 16:47 dc02_add.txt
-rw-r--r--. 1 root root 0 Aug 7 16:52 dc02_update.txt
-rw-r--r--. 1 root root 0 Aug 7 16:47 dc03_add.txt
-rw-r--r--. 1 root root 0 Aug 7 16:56 dc03_update.txt
新建 dc04 继承 dc03 后再删除dc03
结论:容器之间配置信息的传递,数据卷的生命周期一直持续到没有容器使用它为止。可以使用 docker inspect 查看容器的详细信息显示。
~ docker run -it --name dc04 --volumes-from dc03 ks/centos:1.0
[root@58ac5443836b /]# ls -l /dataVolumeContainer2/
total 0
-rw-r--r--. 1 root root 0 Aug 7 16:43 dc01_add.txt
-rw-r--r--. 1 root root 0 Aug 7 16:47 dc02_add.txt
-rw-r--r--. 1 root root 0 Aug 7 16:52 dc02_update.txt
-rw-r--r--. 1 root root 0 Aug 7 16:47 dc03_add.txt
-rw-r--r--. 1 root root 0 Aug 7 16:56 dc03_update.txt
~ docker rm -f dc03
~ docker exec -it dc04 touch /dataVolumeContainer2/dc04_add.txt
~ docker exec -it dc04 ls -l /dataVolumeContainer2/
total 0
-rw-r--r--. 1 root root 0 Aug 7 16:43 dc01_add.txt
-rw-r--r--. 1 root root 0 Aug 7 16:47 dc02_add.txt
-rw-r--r--. 1 root root 0 Aug 7 16:52 dc02_update.txt
-rw-r--r--. 1 root root 0 Aug 7 16:47 dc03_add.txt
-rw-r--r--. 1 root root 0 Aug 7 16:56 dc03_update.txt
-rw-r--r--. 1 root root 0 Aug 7 16:59 dc04_add.txt
6 Dockerfile 解析
:::warning 在上一个步骤中:
- 手动编写一个 Dockerfile 文件,当然,必须要符合 file 的规范
- 有这个文件后,直接 docker build 执行,获取一个自定义的镜像
- docker run 运行成一个容器
:::
6.1 Dockerfile 是什么
:::warning
Dockerfile 是用来构建 Docker 镜像的文本文件(类似于Shell脚本),是由一条条构建镜像所需的指令和参数构成的脚本。:::
概述
官网
https://docs.docker.com/engine/reference/builder/
构建三步骤
- 编写Dockerfile文件
- docker build 命令构建镜像
- docker run 依镜像运行容器实例
案例:以 CentOS 为例
FROM scratch
ADD centos-7-x86_64-docker.tar.xz /
LABEL \
org.label-schema.schema-version="1.0" \
org.label-schema.name="CentOS Base Image" \
org.label-schema.vendor="CentOS" \
org.label-schema.license="GPLv2" \
org.label-schema.build-date="20201113" \
org.opencontainers.image.title="CentOS Base Image" \
org.opencontainers.image.vendor="CentOS" \
org.opencontainers.image.licenses="GPL-2.0-only" \
org.opencontainers.image.created="2020-11-13 00:00:00+00:00"
# Default command
CMD ["/bin/bash"]
6.2 Dockerfile 构建过程解析
6.2.1 Dockerfile 内容基础知识
:::warning
- 每条保留字指令都
**<font style="color:#E8323C;">必须为大写字母</font>**
并且后面要跟随至少一个参数 - 指令按照从上到下,顺序执行
- # 表示注释
- 每条指令都会创建一个新的镜像层并对镜像进行提交
:::
6.2.2 Docker 执行 Dockerfile 大致流程
:::warning
- docker 从基础镜像运行一个容器
- 执行一条指令并对容器作出修改
- 执行类似 docker commit 的操作提交一个新的镜像层
- docker 再基于刚提交的镜像运行一个新容器
- 执行 dockerfile 中的下一条指令直到所有指令都执行完成
- 最后将所有指令汇集的容器执行 docker commit 操作提交镜像
- 并将最后所有指令汇集的容器删除
:::
6.2.3 小总结
:::warning 从应用软件的角度来看,Dockerfile、Docker镜像与Docker容器分别代表软件的三个不同阶段
- Dockerfile 是软件的原材料
- Docker 镜像是软件的交付品
- Docker 容器则可以认为是软件镜像的运行态,也即依照镜像运行的容器实例
Dockerfile 面向开发,Docker 镜像成为交付标准,Docker 容器则涉及部署与运维,三者缺一不可,合力充当Docker 体系的基石。
:::
- Dockerfile,需要定义一个 Dockerfile文件,Dockerfile 定义了进程需要的一切东西。Dockerfile 涉及的内容包括执行代码或者是文件、环境变量、依赖包、运行时环境、动态链接库、操作系统的发行版、服务进程和内核进程(当应用进程需要和系统服务和内核进程打交道,这时需要考虑如何设计 namespace 的权限控制)等等。
- Docker 镜像,在用Dockerfile 定义一个文件之后,docker build 时产生一个Docker 镜像,当运行 Docker 镜像时会真正开始提供服务。
- Docker 容器,容器直接提供服务的。
6.3 Dockerfile 保留字体系结构
FROM debian:bullseye-slim
# add our user and group first to make sure their IDs get assigned consistently, regardless of whatever dependencies get added
RUN groupadd -r -g 999 redis && useradd -r -g redis -u 999 redis
# grab gosu for easy step-down from root
# https://github.com/tianon/gosu/releases
ENV GOSU_VERSION 1.14
RUN set -eux; \
savedAptMark="$(apt-mark showmanual)"; \
apt-get update; \
apt-get install -y --no-install-recommends ca-certificates dirmngr gnupg wget; \
rm -rf /var/lib/apt/lists/*; \
dpkgArch="$(dpkg --print-architecture | awk -F- '{ print $NF }')"; \
wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch"; \
wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch.asc"; \
export GNUPGHOME="$(mktemp -d)"; \
gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4; \
gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu; \
gpgconf --kill all; \
rm -rf "$GNUPGHOME" /usr/local/bin/gosu.asc; \
apt-mark auto '.*' > /dev/null; \
[ -z "$savedAptMark" ] || apt-mark manual $savedAptMark > /dev/null; \
apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \
chmod +x /usr/local/bin/gosu; \
gosu --version; \
gosu nobody true
ENV REDIS_VERSION 7.0.4
ENV REDIS_DOWNLOAD_URL http://download.redis.io/releases/redis-7.0.4.tar.gz
ENV REDIS_DOWNLOAD_SHA f0e65fda74c44a3dd4fa9d512d4d4d833dd0939c934e946a5c622a630d057f2f
RUN set -eux; \
\
savedAptMark="$(apt-mark showmanual)"; \
apt-get update; \
apt-get install -y --no-install-recommends \
ca-certificates \
wget \
\
dpkg-dev \
gcc \
libc6-dev \
libssl-dev \
make \
; \
rm -rf /var/lib/apt/lists/*; \
\
wget -O redis.tar.gz "$REDIS_DOWNLOAD_URL"; \
echo "$REDIS_DOWNLOAD_SHA *redis.tar.gz" | sha256sum -c -; \
mkdir -p /usr/src/redis; \
tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=1; \
rm redis.tar.gz; \
\
# disable Redis protected mode [1] as it is unnecessary in context of Docker
# (ports are not automatically exposed when running inside Docker, but rather explicitly by specifying -p / -P)
# [1]: https://github.com/redis/redis/commit/edd4d555df57dc84265fdfb4ef59a4678832f6da
grep -E '^ *createBoolConfig[(]"protected-mode",.*, *1 *,.*[)],$' /usr/src/redis/src/config.c; \
sed -ri 's!^( *createBoolConfig[(]"protected-mode",.*, *)1( *,.*[)],)$!\10\2!' /usr/src/redis/src/config.c; \
grep -E '^ *createBoolConfig[(]"protected-mode",.*, *0 *,.*[)],$' /usr/src/redis/src/config.c; \
# for future reference, we modify this directly in the source instead of just supplying a default configuration flag because apparently "if you specify any argument to redis-server, [it assumes] you are going to specify everything"
# see also https://github.com/docker-library/redis/issues/4#issuecomment-50780840
# (more exactly, this makes sure the default behavior of "save on SIGTERM" stays functional by default)
\
# https://github.com/jemalloc/jemalloc/issues/467 -- we need to patch the "./configure" for the bundled jemalloc to match how Debian compiles, for compatibility
# (also, we do cross-builds, so we need to embed the appropriate "--build=xxx" values to that "./configure" invocation)
gnuArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"; \
extraJemallocConfigureFlags="--build=$gnuArch"; \
# https://salsa.debian.org/debian/jemalloc/-/blob/c0a88c37a551be7d12e4863435365c9a6a51525f/debian/rules#L8-23
dpkgArch="$(dpkg --print-architecture)"; \
case "${dpkgArch##*-}" in \
amd64 | i386 | x32) extraJemallocConfigureFlags="$extraJemallocConfigureFlags --with-lg-page=12" ;; \
*) extraJemallocConfigureFlags="$extraJemallocConfigureFlags --with-lg-page=16" ;; \
esac; \
extraJemallocConfigureFlags="$extraJemallocConfigureFlags --with-lg-hugepage=21"; \
grep -F 'cd jemalloc && ./configure ' /usr/src/redis/deps/Makefile; \
sed -ri 's!cd jemalloc && ./configure !&'"$extraJemallocConfigureFlags"' !' /usr/src/redis/deps/Makefile; \
grep -F "cd jemalloc && ./configure $extraJemallocConfigureFlags " /usr/src/redis/deps/Makefile; \
\
export BUILD_TLS=yes; \
make -C /usr/src/redis -j "$(nproc)" all; \
make -C /usr/src/redis install; \
\
# TODO https://github.com/redis/redis/pull/3494 (deduplicate "redis-server" copies)
serverMd5="$(md5sum /usr/local/bin/redis-server | cut -d' ' -f1)"; export serverMd5; \
find /usr/local/bin/redis* -maxdepth 0 \
-type f -not -name redis-server \
-exec sh -eux -c ' \
md5="$(md5sum "$1" | cut -d" " -f1)"; \
test "$md5" = "$serverMd5"; \
' -- '{}' ';' \
-exec ln -svfT 'redis-server' '{}' ';' \
; \
\
rm -r /usr/src/redis; \
\
apt-mark auto '.*' > /dev/null; \
[ -z "$savedAptMark" ] || apt-mark manual $savedAptMark > /dev/null; \
find /usr/local -type f -executable -exec ldd '{}' ';' \
| awk '/=>/ { print $(NF-1) }' \
| sort -u \
| xargs -r dpkg-query --search \
| cut -d: -f1 \
| sort -u \
| xargs -r apt-mark manual \
; \
apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \
\
redis-cli --version; \
redis-server --version
RUN mkdir /data && chown redis:redis /data
VOLUME /data
WORKDIR /data
COPY docker-entrypoint.sh /usr/local/bin/
ENTRYPOINT ["docker-entrypoint.sh"]
EXPOSE 6379
CMD ["redis-server"]
6.3.1 FROM
基础镜像,当前新镜像是基于哪个镜像的,指定一个已经存在的镜像作为模板,第一条必须是 from。6.3.2 MAINTAINER
镜像维护者的姓名和邮箱地址6.3.3 RUN
容器构建时需要运行的命令(容器启动前做的一下预操作
),在 docker build 命令构建镜像的时候,就会执行RUN的部分。一个 RUN 的操作就会添加一层镜像层,Dockerfile 最多 127 层镜像层。
两种格式
- Shell 格式
RUN <命令行命令>
# <命令行命令> 等同于,在终端操作的 shell 指令
# 例如:
RUN yum install -y vim
- exec 格式
RUN ["可执行文件", "参数1", "参数2"]
# 例如:
# RUN ["./test.php", "dev", "offline"] 等价于 RUN ./test.php dev offline
RUN 是在 docker build 时运行
6.3.4 EXPOSE
EXPOSEEXPOSE 定义说明里面的服务端口。 该指令通知 Docker 容器在运行时侦听指定的网络端口。您可以指定端口是在 TCP 还是 UDP 上侦听,如果未指定协议,则默认值为 TCP。EXPOSE。 该指令实际上并不发布端口。它充当构建映像的人员和运行容器的人员之间的一种文档类型,有关要发布哪些端口。若要在运行容器时实际发布端口,请使用 标志 on 发布和映射一个或多个端口,或使用标志发布所有公开的端口并将其映射到高阶端口。EXPOSE-pdocker run-P[ / …]
6.3.5 WORKDIR
WORKDIR /path/to/workdir指定在创建容器后,终端默认登录的进来工作目录,一个落脚点
6.3.6 USER
指定该镜像以什么样的用户去执行,如果都不指定,默认是 root6.3.7 ENV
用来在构建镜像过程中设置环境变量
ENV MY_PATH /usr/mytest
这个环境变量可以在后续的任何 RUN 指令中使用,这就如同在命令前面指定了环境变量前缀一样;
也可以在其他指令中直接使用这些环境变量
比如:WORKDIR $MY_PATH
6.3.8 ADD
ADD [—chown=将宿主机目录下的文件拷贝进镜像并且会自动处理 URL 和解压 tar 压缩包。 该功能仅在用于构建 Linux 容器的 Dockerfiles 上受支持,在 Windows 容器上不起作用。由于用户和组所有权概念不会在 Linux 和 Windows 之间转换,因此使用 和 用于将用户和组名称转换为 ID 会将此功能限制为仅适用于基于 Linux 操作系统的容器。 如果 是可识别的压缩格式(标识、gzip、bzip2 或 xz)的本地 tar 存档,则将其解压缩为目录。来自远程 URL 的资源不会解压缩。当复制或解压缩目录时,它的行为与 相同,结果是:: ADD [—chown=] … : ] [“ “,… “ “]
ADD 命令支持将远程URL的资源,但是 Docker 官方不建议直接用远程url,所以还是先下载到主机
是 COPY 的升级版。6.3.9 COPY
类似 ADD,拷贝文件和目录到镜像中。 将从构建上下文目录中 <源路径> 的文件/目录复制到新的一层的镜像内的<目标路径>位置:::warning COPY src dest
COPY [“src”, “dest”]
:::
6.3.10 VOLUME
VOLUME [“/data”]容器数据卷,用于数据保存和持久化工作 该指令创建具有指定名称的装入点,并将其标记为保存来自本机主机或其他容器的外部装入卷。该值可以是 JSON 数组,也可以是具有多个参数(如 或 )的纯字符串。有关通过 Docker 客户端的更多信息/示例和挂载说明,请参阅通过卷共享目录文档。
VOLUMEVOLUME [“/var/log/“]VOLUME /var/logVOLUME /var/log /var/db
6.3.11 CMD
**<font style="color:#E8323C;">指定容器启动(docker run)后的要干的事情</font>**
CMD 容器启动命令
CMD 指令的格式和 RUN 相似,也是两种格式:
- shell 格式:CMD <命令>
- exec 格式:CMD [“可执行文件”, “参数1”, “参数2”, ……]
- 参数列表格式:CMD[“参数1”, “参数2” ……]。在指定了 ENTRYPOINT 指定后,用 CMD 指定具体的参数
注意
Dockerfile 中可以有很多个 CMD 指令,
<font style="color:#E8323C;">但是只有最后一个生效,CMD会被docker run 之后的参数替换</font>
参考官网Tomcat 的 dockerfile 演示介绍
演示覆盖操作
# 官网Dockerfile文件内容
......
EXPOSE 8080
CMD ["catalina.sh", "run"]
$ docker run -it -p 8080:8080 -d billygoo/tomcat8-jdk8:latest /bin/bash
# 浏览器将无法访问8080 Tomcat 默认网页
它和前面 RUN 命令的区别
**<font style="color:#E8323C;">CMD 是在 docker run 时运行</font>**
**<font style="color:#E8323C;">RUN 是在 docker build 时运行</font>**
6.3.12 ENTRYPOINT
也是用来指定一个容器启动(docker run)时要运行的命令
类似于 CMD 指令,但是 <font style="color:#E8323C;">ENTRYPOINT 不会被 docker run 后面的命令覆盖,而且这些命令行参数会被当做参数送给 ENTRYPOINT 指令指定的程序</font>
命令格式和案例说明
命令格式:
ENTRYPOINT ["executable", "param1", "param2"]
ENTRYPOINT 可以和 CMD 一起使用,一般是"变参"才会使用 CMD,这里的 CMD 等于是在给 ENTRYPOINT 传参
当指定了 ENTRYPOINT 后,CMD 的含义就发生了变化,
不再是直接运行其命令而是将 CMD 的内容作为参数传递给 ENTRYPOINT 指令,它两个组合会变成 <ENTRYPOINT> "<CMD>"
案例如下:假设已通过Dockerfile 构建了 "nginx:test 镜像"
FROM nginx
EXPOSE 80
ENTRYPOINT ["nginx", "-c"] # 定参
CMD ["/etc/nginx/nginx.conf"] # 变参
是否传参 | 按照dockerfile编写执行 | 传参运行 |
---|---|---|
Docker命令 | docker run nginx:test | docker run nginx:test /etc/nginx/new.conf |
衍生出的实际命令 | nginx -c /etc/nginx/nginx.conf | nginx -c /etc/nginx/new.conf |
优点:在执行 docker run 的时候可以指定 ENTRYPOINT 运行所需的参数。
注意:如果 Dockerfile 中如果存在多个 ENTRYPOINT 指令,仅最后一个生效。
CMD 和 ENTRYPOINT 区别
:::warning CMD # 指定这个容器启动的时候要运行的命令,不可以追加命令
ENTRYPOINT # 指定这个容器启动的时候要运行的命令,可以追加命令
:::
6.3.13 ONBUILD
当构建一个被继承的 Dockerfile 时运行命令,父镜像在被子镜像的 ONBUILD 被触发。
该指令向映像添加了一个触发器指令,该指令将在以后用作另一个生成的基础时执行。触发器将在下游构建的上下文中执行,就好像它已立即插入到下游指令之后一样。ONBUILDFROMDockerfile 任何构建指令都可以注册为触发器。 如果您正在构建一个映像,该映像将用作构建其他映像的基础,例如应用程序构建环境或可以使用用户特定配置进行自定义的守护程序,这将非常有用。
ONBUILD ADD . /app/src
ONBUILD RUN /usr/local/bin/python-build --dir /app/src
范例:
# 设置基础镜像
FROM centos:centos7.9.2009
# 添加 curl 软件包信息
RUN yum install -y curl
# 查看当前IP地址的归属地信息
# ENTRYPOINT [ "curl", "-s", "https://ip.cn" ]
ENTRYPOINT [ "curl", "-L", "http://ip.tool.lu" ]
ONBUILD RUN echo "Father image onbuild -----> Bye Bye Bye"
~ docker build -t myip-father:1.0 .
~ docker images myip-father:1.0
REPOSITORY TAG IMAGE ID CREATED SIZE
myip-father 1.0 8a88395f970d 19 seconds ago 381MB
# 设置基础镜像
FROM myip-father:1.0
# 添加 curl 软件包信息
RUN yum install -y curl
# 查看当前IP地址的归属地信息
# ENTRYPOINT [ "curl", "-s", "https://ip.cn" ]
ENTRYPOINT [ "curl", "-L", "http://ip.tool.lu" ]
~ docker build -t myip-san:1.0 .
Sending build context to Docker daemon 12.8kB
Step 1/3 : FROM myip-father:1.0
# Executing 1 build trigger
---> Running in a43745fd0d1d
Father image onbuild -----> Bye Bye Bye
Removing intermediate container a43745fd0d1d
---> b8250e846205
Step 2/3 : RUN yum install -y curl
---> Running in a8c963470adc
Loaded plugins: fastestmirror, ovl
Loading mirror speeds from cached hostfile
* base: mirrors.ustc.edu.cn
* extras: mirrors.ustc.edu.cn
* updates: mirrors.cn99.com
Package curl-7.29.0-59.el7_9.1.x86_64 already installed and latest version
Nothing to do
Removing intermediate container a8c963470adc
---> dc891edbbcad
Step 3/3 : ENTRYPOINT [ "curl", "-L", "http://ip.tool.lu" ]
---> Running in 70e9ebe88871
Removing intermediate container 70e9ebe88871
---> 836a84139e73
Successfully built 836a84139e73
Successfully tagged myip-san:1.0
2.3.14 小总结
6.4 案例
6.4.1 Base 镜像
DockerHub 中 99% 的镜像都是通过在 base 镜像中安装和配置需要的软件构建出来的。
FROM scratch
ADD centos-7-x86_64-docker.tar.xz /
LABEL \
org.label-schema.schema-version="1.0" \
org.label-schema.name="CentOS Base Image" \
org.label-schema.vendor="CentOS" \
org.label-schema.license="GPLv2" \
org.label-schema.build-date="20201113" \
org.opencontainers.image.title="CentOS Base Image" \
org.opencontainers.image.vendor="CentOS" \
org.opencontainers.image.licenses="GPL-2.0-only" \
org.opencontainers.image.created="2020-11-13 00:00:00+00:00"
CMD ["/bin/bash"]
6.4.2 自定义 mycentos
- 编写
Hub 默认 CentOS 镜像什么情况
~ docker run -it --name c1 centos:centos7.9.2009 /bin/bash
[root@adacecc7f6ee /]# pwd
/
[root@adacecc7f6ee /]# vim
bash: vim: command not found
[root@adacecc7f6ee /]# ifconfig
bash: ifconfig: command not found
# 1.初始CentOS 运行镜像进入的默认路径是 /
# 2.默认不支持 vim
# 3.默认不支持 ifconfig
:::warning 自定义 myCentOS 目的使我们自己的镜像具备如下:
- 登录后的默认路径
- vim 编辑器
- 查看网络配置 ifconfig 支持
:::
准备编写 Dockerfile 文件
myCentOS 内容 Dockerfile
FROM centos:centos7.9.2009
MAINTAINER zhongzhiwei <zhongzhiwei@kubesphere.io>
ENV DIR="/tmp"
# 自定义镜像的默认工作目录
WORKDIR $DIR
# 安装 vim 编辑器和查看网络配置 ifconfig
RUN yum install -y vim \
&& yum install -y net-tools
# 暴露默认的端口
EXPOSE 80
RUN echo "Finished -----> Success."
RUN echo "My Work PATH is $DIR"
CMD ["/bin/bash"]
- 构建
# 会看到 docker build 命令最后有一个 . (.表示当前目录路径)
~ docker build -t mycentos:1.0 .
- 运行
~ docker run -it --name mc1 mycentos:1.0
[root@c39a02540373 tmp]# pwd
/tmp
[root@c39a02540373 tmp]# vim --version | head -n 1
VIM - Vi IMproved 7.4 (2013 Aug 10, compiled Dec 15 2020 16:44:08)
[root@c39a02540373 tmp]# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.17.0.4 netmask 255.255.0.0 broadcast 172.17.255.255
ether 02:42:ac:11:00:04 txqueuelen 0 (Ethernet)
RX packets 6 bytes 516 (516.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
- 列出镜像的变更历史
# docker history 镜像名或者镜像ID
~ docker image history mycentos:1.0
IMAGE CREATED CREATED BY SIZE COMMENT
975647eab327 4 minutes ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0B
12a96e2a2aab 4 minutes ago /bin/sh -c yum install -y vim && yum ins… 233MB
31e37a38abe0 6 minutes ago /bin/sh -c #(nop) WORKDIR /tmp 0B
1b08e0d84fb4 6 minutes ago /bin/sh -c #(nop) ENV DIR=/tmp 0B
db9b94e52e6a 6 minutes ago /bin/sh -c #(nop) MAINTAINER zhongzhiwei <z… 0B
eeb6ee3f44bd 10 months ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0B
<missing> 10 months ago /bin/sh -c #(nop) LABEL org.label-schema.sc… 0B
<missing> 10 months ago /bin/sh -c #(nop) ADD file:b3ebbe8bd304723d4… 204MB
6.4.3 CMD / ENTRYPOINT 镜像案例
都是指定一个容器启动时要运行的命令
CMD
- Dockerfile 中可以有多个 CMD 指令,但是只有最后一个生效,CMD 会被 docker run 后的参数替换覆盖
- Case(Tomcat 的讲解演示)
# 正常运行 Tomcat
~ docker run -it -p 8080:8080 -d --name t1 tomcat:8.5.81
~ docker exec -it t1 /bin/bash
root@b76408c5b0ea:/usr/local/tomcat# cp -a webapps.dist/* webapps/
~ curl localhost:8080
# 展示Tomcat的页面
# 替换 Tomcat 的运行命令
~ docker run -it -p 8082:8080 --name t2 tomcat:8.5.81 ls -l
total 128
drwxr-xr-x 2 root root 4096 Jul 28 19:17 bin
-rw-r--r-- 1 root root 19497 Jun 8 21:30 BUILDING.txt
drwxr-xr-x 2 root root 238 Jun 8 21:30 conf
-rw-r--r-- 1 root root 6210 Jun 8 21:30 CONTRIBUTING.md
drwxr-xr-x 2 root root 4096 Jul 28 19:16 lib
-rw-r--r-- 1 root root 57011 Jun 8 21:30 LICENSE
drwxrwxrwx 2 root root 6 Jun 8 21:30 logs
drwxr-xr-x 2 root root 159 Jul 28 19:17 native-jni-lib
-rw-r--r-- 1 root root 1726 Jun 8 21:30 NOTICE
-rw-r--r-- 1 root root 3398 Jun 8 21:30 README.md
-rw-r--r-- 1 root root 7139 Jun 8 21:30 RELEASE-NOTES
-rw-r--r-- 1 root root 16505 Jun 8 21:30 RUNNING.txt
drwxrwxrwx 2 root root 30 Jul 28 19:16 temp
drwxr-xr-x 2 root root 6 Jul 28 19:16 webapps
drwxr-xr-x 7 root root 81 Jun 8 21:30 webapps.dist
drwxrwxrwx 2 root root 6 Jun 8 21:30 work
~ docker ps -l
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
df69579e21b7 tomcat:8.5.81 "ls -l" 55 seconds ago Exited (0) 54 seconds ago t2
ENTRYPOINT
- docker run 之后的参数会被当作参数传递给 ENTRYPOINT ,之后形成新的命令组合
- Case
- 制作 CMD 版可以查看 IP信息的容器
# 设置基础镜像
FROM centos:centos7.9.2009
# 添加 curl 软件包信息
RUN yum install -y curl
# 查看当前IP地址的归属地信息
# CMD [ "curl", "-s", "https://ip.cn" ]
CMD [ "curl", "-L", "http://ip.tool.lu" ]
:::warning curl 命令解释
curl命令可以用来执行下载、发送各种HTTP请求,指定HTTP头部等操作。如果系统没有curl可以使用yum install -y curl安装,也可以下载安装。
curl 是将下载文件输出到 stdout
使用命令:curl http://www.baidu.com
执行后,www.baidu.com 的 html 就会显示在屏幕上了
这是最简单的使用方法。用这个命令获得了http:;/curl.haxx.se指向的页面,同样,如果这里的URL指向的是一个文件或者一幅图都可以直接下载到本地。如果下载的是HTML文档,那么缺省的将只显示文件头部,即HTML文档的header。要全部显示,请加参数-i。
:::
~ docker build -t myip:2.0 .
~ docker run -it --name myip-demo myip:2.0
当前IP: 139.198.105.99
归属地: 中国 北京 北京
- 问题
如果我们希望展示HTTP的头信息,就需要加上 -i 参数
~ docker run -it --name myip-demo myip:1.0
当前IP: 139.198.105.99
归属地: 中国 北京 北京
~ docker run -it --name myip-node1 myip:2.0 -i
docker: Error response from daemon: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: exec: "-i": executable file not found in $PATH: unknown.
- WHY
我们可以看到可执行文件找不到的报错,executable file not found。
之前我们说过,跟在镜像名后面的是 command,运行时会替换CMD的默认值。
因此这里的 -i 替换了原来的CMD,而不是添加在原来的 curl -s http://ip.tool.lu 后面。而-i根本不是命令,所以自然找不到。
那么如果我们希望加入-i这参数,我们就必须重新完整的输入这个命令:
$ docker run myip curl -s http://ip.tool.lu -i
- 制作 ENTRYPOINT 版可以查看 IP信息的容器
# 设置基础镜像
FROM centos:centos7.9.2009
# 添加 curl 软件包信息
RUN yum install -y curl
# 查看当前IP地址的归属地信息
# ENTRYPOINT [ "curl", "-s", "https://ip.cn" ]
ENTRYPOINT [ "curl", "-L", "http://ip.tool.lu" ]
范例:
~ docker build -t myip:3.0 .
~ docker run -it --name myip-node01 myip:3.0
当前IP: 139.198.105.99
归属地: 中国 北京 北京
~ docker run -it --name myip-node02 myip:3.0 -i
HTTP/1.1 301 Moved Permanently
Server: nginx
Date: Mon, 08 Aug 2022 03:18:27 GMT
Content-Type: text/html
Content-Length: 162
Connection: keep-alive
Location: https://ip.tool.lu/
HTTP/1.1 200 OK
Server: nginx
Date: Mon, 08 Aug 2022 03:18:27 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 59
Connection: keep-alive
Vary: Accept-Encoding
Strict-Transport-Security: max-age=15768000
当前IP: 139.198.105.99
归属地: 中国 北京 北京
:::warning CMD 和 ENTRYPOINT 可以理解为 覆盖跟追加组合继续使用的区别。
:::
6.4.4 自定义 Tomcat 9
- mkdir -pv /mydockerfile/tomcat9 ; cd /mydockerfile/tomcat9
mkdir -pv /mydockerfile/tomcat9 ; cd /mydockerfile/tomcat9
- 在上述目录下 touch c.txt
touch /mydockerfile/tomcat9/c.txt
echo "Hello,Docker"> /mydockerfile/tomcat9/c.txt
- 将 jdk 和 tomcat 安装的压缩包拷贝进到上一级目录(jdk-8u301-linux-x64.tar.gz 和 apache-tomcat-9.0.65.tar.gz)
~ tree
.
├── apache-tomcat-9.0.65.tar.gz
├── c.txt
└── jdk-8u301-linux-x64.tar.gz
0 directories, 3 files
- 在 /mydockerfile/tomcat9 目录下新建 Dockerfile 目录内容
FROM centos:centos7.9.2009
MAINTAINER zhongzhiwei <zhongzhiwei@kubesphere.io>
# 指定工作目录
ENV MYPATH="/usr/local/src"
WORKDIR $MYPATH
# 安装相应的依赖包
RUN yum install -y vim net-tools glibc.i686
# 将测试文件拷贝到容器内
# 把宿主机当前上下文的 c.txt 拷贝到容器 /usr/local/src/ 目录下
COPY c.txt /usr/local/src/cincontainer.txt
# 将应用压缩包拷贝并解压到容器目录内
ADD apache-tomcat-9.0.65.tar.gz $MYPATH
ADD jdk-8u301-linux-x64.tar.gz $MYPATH
# 设置应用的软链接
RUN ln -s $MYPATH/jdk1.8.0_301 $MYPATH/java \
&& ln -s $MYPATH/apache-tomcat-9.0.65 $MYPATH/tomcat
# 配置java环境变量
ENV JAVA_HOME=/usr/local/src/java
ENV JRE_HOME=${JAVA_HOME}/jre
ENV CLASSPATH=${JAVA_HOME}/lib/dt.jar:${JAVA_HOME}/lib/tools.jar:${JRE_HOME}/lib:$CLASSPATH
ENV CATALINA_BASE="/usr/local/src/tomcat"
ENV CATALINA_HOME="/usr/local/src/tomcat"
ENV PATH=${JAVA_HOME}/bin:${CATALINA_HOME}/bin:${CATALINA_HOME}/lib:${PATH}
# 容器运行时监听的端口
EXPOSE 8080
# ENTRYPOINT ["/usr/local/src/tomcat/bin/startup.sh"]
# CMD ["/usr/local/src/tomcat/bin/catalina.sh", "run"]
# 启动运行Tomcat
CMD /usr/local/src/tomcat/bin/startup.sh && tail -F /usr/local/src/tomcat/logs/catalina.out
- 构建 -> 构建完毕
docker build -t mytomcat:2.0 .
- docker run 运行 -> 备注
### 运行容器
~ docker run -it -d --name mt2 -p 8080:8080 mytomcat:2.0
~ docker exec -it mt2 /bin/bash
[root@60fca4afd5a8 src]# pwd
/usr/local/src
[root@60fca4afd5a8 src]# ls -l
total 4
drwxr-xr-x 1 root root 42 Aug 8 07:01 apache-tomcat-9.0.65
-rw-r--r-- 1 root root 13 Aug 8 06:45 cincontainer.txt
lrwxrwxrwx 1 root root 27 Aug 8 07:01 java -> /usr/local/src/jdk1.8.0_301
drwxr-xr-x 8 10143 10143 273 Jun 9 2021 jdk1.8.0_301
lrwxrwxrwx 1 root root 35 Aug 8 07:01 tomcat -> /usr/local/src/apache-tomcat-9.0.65
~ curl localhost:8080
# 可以查看到Tomcat的页面信息
~ docker logs -f mt2
# 可以查看到 Tomcat的日志信息
### 运行容器
~ docker run -d -p 9080:8080 --name mt1 \
-v /mydockerfile/tomcat9/test:/usr/local/src/tomcat/webapps/test \
-v /mydockerfile/tomcat9/logs:/usr/local/src/tomcat/logs \
--privileged=true mytomcat:2.0
~ tree /mydockerfile/tomcat9/
/mydockerfile/tomcat9/
├── apache-tomcat-9.0.65.tar.gz
├── c.txt
├── Dockerfile
├── jdk-8u301-linux-x64.tar.gz
├── logs
│ ├── catalina.2022-08-08.log
│ ├── catalina.out
│ ├── host-manager.2022-08-08.log
│ ├── localhost.2022-08-08.log
│ ├── localhost_access_log.2022-08-08.txt
│ └── manager.2022-08-08.log
└── test
~ docker exec -it mt1 java -version
java version "1.8.0_301"
Java(TM) SE Runtime Environment (build 1.8.0_301-b09)
Java HotSpot(TM) 64-Bit Server VM (build 25.301-b09, mixed mode)
~ docker exec -it mt1 cat cincontainer.txt
Hello,Docker
- 验证
浏览器打开 http://
- 结合前述的容器卷将测试的 web 服务 test 发布
- 总体概述
- web.xml
- a.jsp
- 测试
~ cd /mydockerfile/tomcat9/test ; mkdir WEB-INF
~ cat > /mydockerfile/tomcat9/test/WEB-INF/web.xml <<EOF
<?xml version="1.0" encoding="UTF-8?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID" version="2.5">
<display-name>test</display-name>
</web-app>
EOF
~ cat > /mydockerfile/tomcat9/test/a.jsp <<EOF
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
------ welcome ------
<%="i am in docker tomcat self "%>
<br>
<br>
<% System.out.println(" ======> Welcome docker tomcat!"); %>
</body>
</html>
EOF
~ tree -p
.
├── [-rw-r--r--] a.jsp
└── [drwxr-xr-x] WEB-INF
└── [-rw-r--r--] web.xml
1 directory, 2 files
~ docker restart mt1
6.5 Dockerfile 小总结
:::warning Dockerfile 就要符合 Docker 的规范,FROM 基础镜像,MAINTAINER 设置作者,RUN 运行Linux命令,EXPOSE 暴露端口,WORKDIR 设置工作目录,ENV 设置环境变量,ADD 带解压功能的COPY,COPY 就是将宿主机文件拷贝到容器中,不做任何操作,VOLUME 设置容器卷,CMD ENTRYPOTINT 都是在容器启动的时候默认运行的指令,CMD 会被 docker run 参数替换,而 ENTRYPOINT 则是作为参数追加。
:::
7 Docker 常用安装
总体步骤
- 搜索镜像
- 拉取镜像
- 查看镜像
- 启动容器(运行镜像)
- 停止容器
- 移除容器
7.1 安装 Tomcat
# docker hub 上面查找tomcat 镜像
~ docker search tomcat
# 从 docker hub 上拉取 tomcat 镜像到本地
# 1.官网命令
# 2.拉取完成
~ docker pull tomcat:8.0.53
# docker images 查看是否有拉取到的 tomcat
~ docker images tomcat:8.0.53
REPOSITORY TAG IMAGE ID CREATED SIZE
tomcat 8.0.53 ef6a7c98d192 3 years ago 356MB
# 使用 tomcat 镜像创建容器(也叫运行镜像)
# --name 指定容器的名称
# -p 主机端口:容器端口
# -P 随机主机端口
# -i 交互 ; -t 终端
# -d 后台运行
~ docker run -it --name tomcat-node1 -p 8080:8080 \
-v /mydocker/tomcat-node1/test:/usr/local/tomcat/webapps/test -d tomcat:8.0.53
7.2 安装 MySQL
- 使用 MySQL镜像
# docker hub 上面查找 mysql 镜像
~ docker search --limit 3 mysql
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
mysql MySQL is a widely used, open-source relation… 12984 [OK]
mariadb MariaDB Server is a high performing open sou… 4974 [OK]
percona Percona Server is a fork of the MySQL relati… 583 [OK]
# 从docker hub上(阿里云加速器)拉取mysql镜像到本地标签为5.6
~ docker pull mysql:5.6
# 使用 mysql5.6 镜像创建容器(也叫运行镜像)
# 命令说明:
# -p 12345:3306:将主机的12345端口映射到docker容器的3306端口。
# --name mysql:运行服务名字
# -v /zzyyuse/mysql/conf/:/etc/mysq/conf.d:将主机/zyyuse/mysql录下的conf/my.cnf 挂载到容器的/etc/mysql/conf.d
# -v /zzyyuse/mysql/logs:/logs:将主机/zzyyuse/mysql目录下的 logs目录挂载到容器的 /logs。
# -v /zzyyuse/mysq/data:/varlib/mysql:将主机/zzyyuse/mysql目录下的data目录挂载到容器的 /var/lib/mysql
# -e MYSQL_ROOT_PASSWORD=123456:初始化 root用户的密码。
# -d mysql:5.6:后台程序运行mysal5.6
~ docker run -it --name mysql-node1 -d \
-e MYSQL_ROOT_PASSWORD=123456 \
-e MYSQL_DATABASE=kubesphere \
--restart=always -p 3306:3306 \
-v /mydocker/mysql56/conf:/etc/mysql/conf.d \
-v /mydocker/mysql56/logs:/logs \
-v /mydocker/mysql56/data:/var/lib/mysql \
mysql:5.6
~ cat > /mydocker/mysql56/conf/my.cnf <<EOF
[client]
default-character-set=utf8mb4
[mysql]
default-character-set=utf8mb4
[mysqld]
init_connect='SET NAMES utf8mb4'
character-set-server=utf8mb4
collation-server=utf8mb4_unicode_ci
skip-character-set-client-handshake
skip-name-resolve
EOF
~ docker exec -it mysql-node1 /bin/bash
root@d17ed8b774a9:/# mysql -uroot -p123456
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| kubesphere |
| mysql |
| performance_schema |
+--------------------+
4 rows in set (0.00 sec)
mysql> use kubesphere;
Database changed
mysql> create table t_book(id int not null primary key , bookName varchar(20));
Query OK, 0 rows affected (0.04 sec)
mysql> show tables;
+----------------------+
| Tables_in_kubesphere |
+----------------------+
| t_book |
+----------------------+
1 row in set (0.00 sec)
mysql> insert into t_book values(1,'docker');
Query OK, 1 row affected (0.01 sec)
mysql> select * from t_book;
+----+----------+
| id | bookName |
+----+----------+
| 1 | docker |
+----+----------+
1 row in set (0.00 sec)
- 外部 Win10 也来连接运行在 docker 上的 mysql 服务
:::color1 宿主机防火墙记得开启对应端口的访问
mysql8连接不上的报 Plugin caching_sha2_password的;需要修改加密模式为mysql_native_password
:::
- 使用 Windows 系统或者 Mac 系统的数据库连接工具进行连接操作
- 数据备份小测试(可以不做)
:::color1 docker exec mysql服务容器ID sh -c “exec mysqldump —all-databases -uroot -p’123456’” > /mydocker/all-databases.sql
:::
~ docker exec mysql-node1 sh -c "exec mysqldump --all-databases -uroot -p'123456'" > /mydocker/all-databases.sql
~ ls -lh /mydocker/all-databases.sql
-rw-r--r--. 1 root root 3.3M Aug 8 19:28 /mydocker/all-databases.sql
~ cat /mydocker/all-databases.sql | wc -l
7.3 安装 Redis
# 从docker hub上(阿里云加速器)拉取redis镜像到本地标签为3.2
~ docker pull redis:3.2
~ docker images redis:3.2
REPOSITORY TAG IMAGE ID CREATED SIZE
redis 3.2 87856cc39862 3 years ago 76MB
# 使用 redis3.2 镜像创建容器(也叫运行镜像)
# 使用镜像
~ docker run -p 6379:6379 -d --name redis-node1 \
-v /mydocker/myredis/data:/data \
-v /mydocker/myredis/conf/:/usr/local/etc/redis/ \
redis:3.2 redis-server /usr/local/etc/redis/redis.conf
#redis:3.2 redis-server /usr/local/etc/redis/redis.conf --appendonly yes
# 在主机/mydocker/myredis/conf/redis.conf目录下新建redis.conf文件
# vim /mydocker/myredis/conf/redis.conf
~ cat > /mydocker/myredis/conf/redis.conf <<EOF
appendonly yes
daemonize no
# 设置密码
requirepass 123456
EOF
## RDB是快照持久化记录某一时刻
## AOF是记录步骤的持久化把你的操作记录下来
# 测试redis-cli连接上来
~ docker restart redis-node1
~ docker exec -it redis-node1 /bin/bash # docker exec -it redis-node1 redis-cli
root@4b4b8b8f02ed:/data# redis-cli
127.0.0.1:6379> AUTH 123456
OK
127.0.0.1:6379> SET k1 v1
OK
127.0.0.1:6379> SET k2 v2
OK
127.0.0.1:6379> GET k1
"v1"
127.0.0.1:6379> SHUTDOWN
# 测试持久化文件生成
~ cd /mydocker/myredis/data
~ cat appendonly.aof
*2
$6
SELECT
$1
0
*3
$3
SET
$2
k1
$2
v1
*3
$3
SET
$2
k2
$2
v2
# systemctl stop firewall 关闭防火墙
7.4 安装 Nginx
~ docker pull nginx:1.23.1
~ mkdir -pv /mydocker/nginx/conf/ ; mkdir /mydocker/nginx/html/
~ docker run -it -p 80:80 -d \
-v /mydocker/nginx/conf/nginx.conf:/etc/nginx/nginx.conf:rw \
-v /mydocker/nginx/html/:/usr/share/nginx/html/ \
--name nginx-node1 nginx:1.23.1
~ cat > /mydocker/nginx/conf/nginx.conf <<EOF
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
include /etc/nginx/conf.d/*.conf;
}
EOF
~ echo "Hello World" > /mydocker/nginx/html/index.html
~ curl localhost
Hello World
8 本地镜像发布到阿里云
8.1 本地镜像发布到阿里云流程
8.2 镜像的生成方法
- 基于当前容器创建一个新的镜像,新功能增强
# -a :提交的镜像作者
# -m :提交时的说明文字
$ docker commit [OPTIONS] 容器ID [REPOSITORY[:TAG]]
- 使用 Dockerfile 文件
8.3 将本地镜像推送到阿里云
- 本地镜像素材原型
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
myubuntu v1.0 a8375a7783cc 9 hours ago 174MB
- 阿里云开发者平台
https://promotion.aliyun.com/ntms/act/kubernetes.html
- 创建仓库镜像
- 选择控制台,进入容器镜像服务
- 选择个人实例
- 命名空间
- 仓库名称(本地仓库)
- 进入管理界面获取脚本
- 将镜像推送到阿里云
将继续推送到阿里云 registry
- 管理界面脚本
- 脚本实例
# 1. 登录阿里云Docker Registry
$ docker login --username=dragon志伟 registry.cn-shenzhen.aliyuncs.com
用于登录的用户名为阿里云账号全名,密码为开通服务时设置的密码。
您可以在访问凭证页面修改凭证密码
# 3. 将镜像推送到Registry
$ docker login --username=dragon志伟 registry.cn-shenzhen.aliyuncs.com
$ docker tag [ImageId] registry.cn-shenzhen.aliyuncs.com/dragonzw_k8s_images/ubuntu:[镜像版本号]
$ docker push registry.cn-shenzhen.aliyuncs.com/dragonzw_k8s_images/ubuntu:[镜像版本号]
# docker tag myubuntu:v1.0 registry.cn-shenzhen.aliyuncs.com/dragonzw_personal_images/myubuntu:v1.0
# docker push registry.cn-shenzhen.aliyuncs.com/dragonzw_personal_images/myubuntu:v1.0
请根据实际镜像信息替换示例中的[ImageId]和[镜像版本号]参数。
8.4 将阿里云上的镜像下载到本地
# 3. 从Registry中拉取镜像
$ docker pull registry.cn-shenzhen.aliyuncs.com/dragonzw_personal_images/ubuntu:[镜像版本号]
~ docker pull registry.cn-shenzhen.aliyuncs.com/dragonzw_personal_images/ubuntu:1.0
~ docker history registry.cn-shenzhen.aliyuncs.com/dragonzw_personal_images/ubuntu:1.0
IMAGE CREATED CREATED BY SIZE COMMENT
e3587595bab1 44 minutes ago /bin/bash 105MB 添加VIM软件
<missing> 9 months ago /bin/sh -c #(nop) CMD ["bash"] 0B
<missing> 9 months ago /bin/sh -c #(nop) ADD file:5d68d27cc15a80653… 72.8MB
~ docker run -itd --name au1 registry.cn-shenzhen.aliyuncs.com/dragonzw_personal_images/ubuntu:1.0 /bin/bash
~ docker exec -it au1 /bin/bash
root@10dc9cc87e81:/# vim --version
VIM - Vi IMproved 8.1 (2018 May 18, compiled Feb 01 2022 09:16:32)
# docker pull registry.cn-shenzhen.aliyuncs.com/dragonzw_personal_images/myubuntu:1.0
9 CentOS 7 安装 Docker
参考Docker官网
- 官网中文安装参考手册
- 确定你是CentOS 7 及以上版本
- yum 安装 gcc 相关
- 卸载旧版本
- 安装需要的软件包
- 设置 stable 镜像仓库
- 更新 yum 软件包索引
- 安装 docker-ce
- 启动 docker
- 测试
cat /etc/redhat-release
CentOS Linux release 7.9.2009 (Core)
# CentOS 7能够上外网
ping -c1 -W1 www.baidu.com
yum install -y gcc gcc-c++
gcc -v
gcc version 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC)
# 卸载 dokcer旧版本
sudo yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
# 使用阿里源的docker软件源
# step 1: 安装必要的一些系统工具
sudo curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo
# sudo wget -O /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo
sudo yum install -y yum-utils device-mapper-persistent-data lvm2
# Step 2: 添加软件源信息
sudo yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# Step 3
# Docker 官方源国内访问慢
# sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
sudo sed -i 's|download.docker.com|mirrors.aliyun.com/docker-ce|' /etc/yum.repos.d/docker-ce.repo
# Step 4: 更新并安装Docker-CE
# 更新 yum 软件包索引
sudo yum makecache fast
sudo yum install -y docker-ce-20.10.10 docker-ce-cli-20.10.10 containerd.io
# 启动 docker
systemctl enable --now docker
# 设置阿里云容器镜像加速器
mkdir -pv /etc/docker/
# 阿里云"registry-mirrors": ["https://po13h3y1.mirror.aliyuncs.com"]
# 网易云"registry-mirrors": ["http://hub-mirror.c.com"]
tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://po13h3y1.mirror.aliyuncs.com"]
}
EOF
systemctl daemon-reload ; systemctl restart docker
# 验证 docker
docker version && docker --help
docker run hello-world
# 查看系统的进程 docker
ps -ef | grep docker
# 卸载
systemctl stop docker
yum remove -y docker-ce-20.10.10 docker-ce-cli-20.10.10 containerd.io
rm -rf /var/lib/docker
范例:脚本实现 Docker 安装
#!/bin/bash
DOCKER_VERSION="20.10.10"
#UBUNTU_DOCKER_VERSION="5:${DOCKER_VERSION}~3-0~`lsb_release -si`-`lsb_release -cs`"
DOCKER_COMPOSE_VERSION=1.29.2
DOCKER_COMPOSE_FILE=docker-compose-Linux-x86_64
COLOR_SUCCESS="echo -e \\033[1;32m"
COLOR_FAILURE="echo -e \\033[1;31m"
END="\033[m"
. /etc/os-release
color () {
RES_COL=60
MOVE_TO_COL="echo -en \\033[${RES_COL}G"
SETCOLOR_SUCCESS="echo -en \\033[1;32m"
SETCOLOR_FAILURE="echo -en \\033[1;31m"
SETCOLOR_WARNING="echo -en \\033[1;33m"
SETCOLOR_NORMAL="echo -en \E[0m"
echo -n "$1" && $MOVE_TO_COL
echo -n "["
if [ $2 = "success" -o $2 = "0" ] ;then
${SETCOLOR_SUCCESS}
echo -n $" OK "
elif [ $2 = "failure" -o $2 = "1" ] ;then
${SETCOLOR_FAILURE}
echo -n $"FAILED"
else
${SETCOLOR_WARNING}
echo -n $"WARNING"
fi
${SETCOLOR_NORMAL}
echo -n "]"
echo
}
install_docker(){
if [ $ID = "centos" -o $ID = "rocky" ];then
if [ $VERSION_ID = "7" ];then
cat > /etc/yum.repos.d/docker.repo <<EOF
[docker]
name=docker
gpgcheck=0
#baseurl=https://mirrors.aliyun.com/docker-ce/linux/centos/7/x86_64/stable/
baseurl=https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/centos/7/x86_64/stable/
EOF
else
cat > /etc/yum.repos.d/docker.repo <<EOF
[docker]
name=docker
gpgcheck=0
#baseurl=https://mirrors.aliyun.com/docker-ce/linux/centos/8/x86_64/stable/
baseurl=https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/centos/8/x86_64/stable/
EOF
fi
yum clean all
${COLOR_FAILURE} "Docker有以下版本"${END}
yum list docker-ce --showduplicates
${COLOR_FAILURE}"5秒后即将安装: docker-"${DOCKER_VERSION}" 版本....."${END}
${COLOR_FAILURE}"如果想安装其它Docker版本,请按ctrl+c键退出,修改版本再执行"${END}
sleep 5
yum -y install docker-ce-$DOCKER_VERSION docker-ce-cli-$DOCKER_VERSION \
|| { color "Base,Extras的yum源失败,请检查yum源配置" 1;exit; }
else
dpkg -s docker-ce &> /dev/null && $COLOR"Docker已安装,退出" 1 && exit
apt update || { color "更新包索引失败" 1 ; exit 1; }
apt -y install apt-transport-https ca-certificates curl software-properties-common || \
{ color "安装相关包失败" 1 ; exit 2; }
curl -fsSL https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/ubuntu/gpg | sudo apt-key add -
add-apt-repository "deb [arch=amd64] https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/ubuntu $(lsb_release -cs) stable"
apt update
${COLOR_FAILURE} "Docker有以下版本"${END}
apt-cache madison docker-ce
${COLOR_FAILURE}"5秒后即将安装: docker-"${UBUNTU_DOCKER_VERSION}" 版本....."${END}
${COLOR_FAILURE}"如果想安装其它Docker版本,请按ctrl+c键退出,修改版本再执行"${END}
sleep 5
apt -y install docker-ce=${UBUNTU_DOCKER_VERSION} docker-ce-cli=${UBUNTU_DOCKER_VERSION}
fi
if [ $? -eq 0 ];then
color "安装软件包成功" 0
else
color "安装软件包失败,请检查网络配置" 1
exit
fi
mkdir -p /etc/docker
tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://po13h3y1.mirror.aliyuncs.com"],
"insecure-registries": ["harbor.kubesphere.com:80"]
}
EOF
systemctl daemon-reload
systemctl enable docker
systemctl restart docker
docker version && color "Docker 安装成功" 0 || color "Docker 安装失败" 1
echo 'alias rmi="docker images -qa|xargs docker rmi -f"' >> ~/.bashrc
echo 'alias rmc="docker ps -qa|xargs docker rm -f"' >> ~/.bashrc
}
install_docker_compose(){
if [ $ID = "centos" -o $ID = "rocky" ];then
${COLOR_SUCCESS}"开始安装 Docker compose....."${END}
sleep 1
if [ ! -e ${DOCKER_COMPOSE_FILE} ];then
curl -L https://github.com/docker/compose/releases/download/${DOCKER_COMPOSE_VERSION}/${DOCKER_COMPOSE_FILE} -o /usr/bin/docker-compose
else
mv ${DOCKER_COMPOSE_FILE} /usr/bin/docker-compose
fi
chmod +x /usr/bin/docker-compose
else
apt -y install docker-compose
fi
if docker-compose --version ;then
${COLOR_SUCCESS}"Docker Compose 安装完成"${END}
else
${COLOR_FAILURE}"Docker compose 安装失败"${END}
exit
fi
}
install_docker
install_docker_compose