docker·
大家好呀,我们今天又又又
来开新坑了,今天这个坑就是Docker了,我们今天开始就要来了解一下Docker了。
博客地址: 云边日落
作者:酒笙
结尾有pdf版,需要自取。
什么是docker
docker发展史
- 在最开始的时候,docker不叫docker,叫dotcloud。这是由几个年轻人成立的小公司,在当时这样的一个小公司混的还算不错,但是还是打不过大厂,paas市场竞争激烈,dotcloud举步维艰,最后这些年轻人不甘心,不能让自己的坚持与努力付之东流,于是便把他们的核心技术开源,也就是docker,在当时的话,docker的主要功能就是把Linux的代码打包,应用在其他开发平台中。最后这个docker就风靡全球,于是乎,dotcloud就索性改名docker了,并且就全身心的投入到了docker的开发之中
docker的应用场景
- Web应用的自动化打包和发布
- 自动化测试和持续继承、发布
- 在服务型环境中部署和调试数据库或其他后台应用
- 从头编译或者拓展现有的openshift或cloud foundry平台来搭建自己的PaaS环境。
docker的优势
- docker 启动快速属于秒级别。虚拟机通常需要几分钟去启动
- docker 需要的资源更少, docker 在操作系统级别进行虚拟化, docker 容器和内核交互,几乎没有性能损耗,性能优于通过 Hypervisor 层与内核层的虚拟化
- docker 更轻量, docker 的架构可以共用一个内核与共享应用程序库,所占内存极小。同样的硬件环境, Docker 运行的镜像数远多于虚拟机数量,对系统的利用率非常高
- 与虚拟机相比, docker 隔离性更弱, docker 属于进程之间的隔离,虚拟机可实现系统级别隔
- 安全性: docker 的安全性也更弱。 Docker 的租户 root 和宿主机 root 等同,一旦容器内的用户从普通用户权限提升为root权限,它就直接具备了宿主机的root权限,进而可进行无限制的操作。虚拟机租户 root 权限和宿主机的 root 虚拟机权限是分离的,并且虚拟机利用如 Intel 的 VT-d 和 VT-x 的 ring-1 硬件隔离技术,这种隔离技术可以防止虚拟机突破和彼此交互,而容器至今还没有任何形式的硬件隔离,这使得容器容易受到攻击
- 可管理性: docker 的集中化管理工具还不算成熟。各种虚拟化技术都有成熟的管理工具,例如 VMware vCenter 提供完备的虚拟机管理能力
- 高可用和可恢复性: docker 对业务的高可用支持是通过快速重新部署实现的。虚拟化具备负载均衡,高可用,容错,迁移和数据保护等经过生产实践检验的成熟保障机制, VMware 可承诺虚拟机 99.999% 高可用,保证业务连续性
- 快速创建、删除:虚拟化创建是分钟级别的, Docker 容器创建是秒级别的, Docker 的快速迭代性,决定了无论是开发、测试、部署都可以节约大量时间
- 交付、部署:虚拟机可以通过镜像实现环境交付的一致性,但镜像分发无法体系化。 Docker 在 Dockerfile 中记录了容器构建过程,可在集群中实现快速分发部署
dockers的三个基本概念
- image(镜像)
- container(容器)
- repository(仓库)
- image(镜像)
- 镜像是docker运行的前提,仓库是存放镜像的地方,那么镜像就是核心了。
Docker
镜像可以看作是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。镜像不包含任何动态数据,其内容在构建之后也不会被改变。
- 我们简单来说一下,这个储存格式-联合文件系统,这是一个分层的问阿金系统,可以将不同的目录挂载到同一个虚拟文件下。那么我们docker的镜像就是使用的这样一个文件系统。
- 下图就是镜像的存储格式,这张图是分层的,最下面一层,上面也是一层层的好像集装箱罗列在一起.这就是镜像最直观的存储方式.下面是操作系统的引导,上面是linux操作系统,再上面是一些相关的软件,如果是我们自己的程序,就可以是tomcat,jdk,再往上是应用代码,每一层是我们自己都可以控制得,最上面一层先忽略不看,因为这是和容器有关的.注意一点,docker镜像系统的每一层都是只读的,然后把每一层加载完成之后这些文件都会被看成是同一个目录,相当于只有一个文件系统.docker的这种文件系统被称之为镜像.
container(容器)
为了便于理解,大家可以把容器想象成虚拟机,每个虚拟机都有自己的文件系统,可以把图1整个一部分看成是文件系统,与虚拟机系统的区别是这里面的文件系统是一层一层的,并且最下面的n层都是只读的,只有上面一层是可写的.为什么要有可写的这层呢?大家的程序运行起来,势必会要写一些日志,写一些文件,或者对系统的某一些文件做一些修改,所以容器在最上面一层创建了可读可写的文件系统.
在程序的运行过程中,如果要写镜像文件时,因为镜像的每一层都是只读的,它会把文件的每一层拷到文件的最上层,然后再对它进行修改,修改之后,当我们的应用读一个文件时会从顶层进行查找,如果没有才会找下一层.
由于容器的最上一层是可以修改的,镜像是不能修改的,这样就能保证镜像可以生成多个容器独立运行,没有任何干扰.
简要的概括就是:容器 = 镜像 + 读写层。
repository(仓库)
Docker
仓库是集中存放镜像文件的场所。镜像构建完成后,可以很容易的在当前宿主上运行,但是, 如果需要在其它服务器上使用这个镜像,我们就需要一个集中的存储、分发镜像的服务,Docker Registry
(仓库注册服务器)就是这样的服务。有时候会把仓库(Repository)
和仓库注册服务器(Registry)
混为一谈,并不严格区分。Docker
仓库的概念跟Git
类似,注册服务器可以理解为GitHub
这样的托管服务。实际上,一个Docker Registry
中可以包含多个仓库(Repository)
,每个仓库可以包含多个标签(Tag)
,每个标签对应着一个镜像。所以说,镜像仓库是Docker
用来集中存放镜像文件的地方类似于我们之前常用的代码仓库。
通常,一个仓库会包含同一个软件不同版本的镜像,而标签就常用于对应该软件的各个版本 。我们可以通过
<仓库名>:<标签>
的格式来指定具体是这个软件哪个版本的镜像。如果不给出标签,将以latest
作为默认标签.。
仓库又可以分为两种形式:
- public(公有仓库)
- private(私有仓库)
Docker Registry
公有仓库是开放给用户使用、允许用户管理镜像的Registry
服务。一般这类公开服务允许用户免费上传、下载公开的镜像,并可能提供收费服务供用户管理私有镜像。- 除了使用公开服务外,用户还可以在本地搭建私有
Docker Registry
。Docker
官方提供了Docker Registry
镜像,可以直接使用做为私有Registry
服务。当用户创建了自己的镜像之后就可以使用push
命令将它上传到公有或者私有仓库,这样下次在另外一台机器上使用这个镜像时候,只需要从仓库上pull
下来就可以了。 - 我们主要把
Docker
的一些常见概念如Image
,Container
,Repository
做了详细的阐述,也从传统虚拟化方式的角度阐述了docker
的优势,我们从下图可以直观地看到Docker
的架构: Docker
使用C/S
结构,即客户端/服务器体系结构。Docker
客户端与Docker
服务器进行交互,Docker服务端负责构建、运行和分发Docker
镜像。Docker
客户端和服务端可以运行在一台机器上,也可以通过RESTful
、stock
或网络接口与远程Docker
服务端进行通信。
- 这张图展示了 Docker 客户端、服务端和
Docker
仓库(即Docker Hub
和Docker Cloud
),默认情况下Docker
会在Docker
中央仓库寻找镜像文件,这种利用仓库管理镜像的设计理念类似于Git
,当然这个仓库是可以通过修改配置来指定的,甚至我们可以创建我们自己的私有仓库。
docker安装
1.下载关于Docker的依赖环境
♾️ python 代码:
yum -y install yum-utils device-mapper-persistent-data lvm2
2.设置下载Docker的镜像源
♾️ python 代码:
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
3.安装Docker
♾️ python 代码:
yum makecache fast
yum -y install docker-ce
4.启动Docker,并设置为开机自动启动,测试
♾️ python 代码:# 启动Docker服务
systemctl start docker
# 设置开机自动启动
systemctl enable docker
# 测试
docker run hello-world
- 查看刚才下载的hello-word镜像
docker images
卸载docker
- 删除依赖
yum remove docker-ce docker-ce-cli containerd.io
- 删除资源
rm -rf /var/lib/docker
rm -rf /var/lib/containerd
# /var/lib/docker docker工作的默认路径
阿里云镜像加速
登录阿里云
{abtn icon="fa-heart-o" color="#f86dc5" href="https://www.aliyun.com/" radius="17px" content="阿里云"/}
- 在弹性计算找到容器计算服务
- 创建账号然后点击镜像工具里面的镜像加速
- 配置使用
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://vjtmk5k2.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
- 查看是否配置成功
cat /etc/docker/daemon.json
/*返回如下
{
"registry-mirrors": ["https://vjtmk5k2.mirror.aliyuncs.com"]
}
*/
运行过程
底层原理
docker是怎样工作做的?
- Docker Engine是一个客户端-服务器应用程序,具有以下主要组件:
- 一个服务器,它是一种长期运行的程序,称为守护进程(dockerd命令)。
- 一个REST API,它指定程序可以用来与守护进程对话并指示它做什么的接口。
- 命令行接口(CLI)客户端(docker命令)。
- Docker是一个Client Server结构的系统,Docker守护进程运行在主机上,然后通过Socket连接从客户 端访问,守护进程从客户端接受命令并管理运行在主机上的容器。
docker为什么比VM快?
- Docker不需要Hypervisor实现硬件资源虚拟化,运行在Docker容器上的程序直接使用的都是实际物理机的硬件资源。因此在CPU、内存利用率上Docker将会在效率上有明显优势。
- Docker利用的是宿主机的内核,而不需要GuestOS。因此,当新建一个容器时,Docker不需要和虚拟机一样重新加载一个操作系统内核。可避免引导寻址、加载操作系统内核返回这个比较费时费资源的过程,当新建一个虚拟机时,虚拟机软件需要加载GuestOS,返回新增过程是分钟级别的。而Docker由于利用宿主机的操作系统,则省略了返回的过程,因此新建一个Docker容器只需要几秒钟。
docker基本命令
帮助命令
♾️ shell 代码:docker version #版本信息
docker info #系统信息
docker 命令 --help #帮助命令
帮助文档地址:https://docs.docker.com/engine/reference/
镜像命令
docker images 查看本机所有镜像
♾️ shell 代码:[root@jiusheng]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest d1165f221234 4 months ago 13.3kB
#REPOSITORY 镜像仓库源
#TAG 镜像标签
#IMAGE ID 镜像id
# CREATED 镜像创建的时间
#SIZE 镜像大小
#可选项
-a , --all #列出所有镜像
-q , --quiet #显示镜像id
docker search 搜索镜像
♾️ shell 代码:# 官网搜索: https://hub.docker.com/
docker search 搜索名
#搜索MySQL镜像
docker search mysql
[root@jiusheng]# docker search mysql
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
mysql MySQL is a widely used, open-source relation… 11147 [ OK]
mariadb MariaDB Server is a high performing open sou… 4228 [OK]
#条件搜索
--filter=STARS=5000 #搜索出来的镜像就是STARS大于5000的
[root@jisuheng]# docker search mysql --filter=STARS=5000
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
mysql MySQL is a widely used, open-source relation… 11147 [OK]
docker pull 下载镜像
♾️ shell 代码:#下载镜像 docker pull 镜像名[:tag] 下载指定版本
docker pull 镜像名 #默认下载最新版本
[root@jiusheng]# docker pull mysql
Using default tag: latest #不填写指定版本,默认下载最新版本
latest: Pulling from library/mysql
b4d181a07f80: Pull complete #分层下载,也就是 docker iamge核心,联合文件系统
b4d181a07f80: Pull complete
a462b60610f5: Pull complete
578fafb77ab8: Pull complete
524046006037: Pull complete
d0cbe54c8855: Pull complete
aa18e05cc46d: Pull complete
fd6f649b1d0a: Pull complete
2a97d48c2fdc: Pull complete
30f0c7db48fc: Pull complete
f5dda8df049e: Pull complete
671b83fd7448: Pull complete
5d9cc55fa997: Pull complete
Digest: sha256:18d8d109aa64673c78aebfb845b929cfdac97a553332f4310f4de8d67ceb03d2
Status: Downloaded newer image for mysql:latest
docker.io/library/mysql:latest
#真实地址等价于 docker pull mysql = docker pull docker.io/library/mysql:latest
#下载指定版本
docker pull mysql:5.7
#具体有哪些版本可以去官网查看,不要乱写
[root@jiusheng]# docker pull mysql:5.7
5.7: Pulling from library/mysql
b4d181a07f80: Already exists #这就是分层下载的好处,只下载不一样的。
a462b60610f5: Already exists
578fafb77ab8: Already exists
524046006037: Already exists
d0cbe54c8855: Already exists
aa18e05cc46d: Already exists
fd6f649b1d0a: Already exists
8a2b858b000b: Pull complete
322182b17422: Pull complete
070e28050a88: Pull complete
613bdfd8796e: Pull complete
Digest: sha256:956e11ac581cad9ac8747a9a1d61b8ffcfa6845e0f23bdbab6ba20a2ad792cbf #这是一个签名
Status: Downloaded newer image for mysql:5.7 #版本
docker.io/library/mysql:5.7
docker rmi 删除镜像
♾️ shell 代码:docker rmi -f 镜像id #删除指定镜像
docker rmi -f 镜像id,镜像id #删除多个指定镜像
docker rmi -f $(docker images -aq) #使用递归删除所有镜像
容器命令
有了镜像之后,才可以创建容器,容器依赖于镜像。
我们这里下载一个centos的镜像
♾️ shell 代码:docker pull centos
新建容器并启动
♾️ shell 代码:docker run [可选参数] images
#参数说明
--name="Name" #容器名字,用于区分容器
-d #后台方式运行
-it #使用交互式运行,并进入容器查看内容
-p #指定容器端口
-p ip : 主机端口 : 容器端口
-p 主机端口 :容器端口 常用
-p 容器端口
-P 随机容器端口
测试,启动并进入容器
♾️ shell 代码:[root@jiusheng]# docker run -it centos /bin/bash
[root@2d13e5147554 /]# ls #查看容器内的centos
bin etc lib lost+found mnt proc run srv tmp var
dev home lib64 media opt root sbin sys usr
[root@2d13e5147554 /]#
退出容器
♾️ shell 代码:exit #停止容器并退出
Ctrl + p + q #容器不停止退出
列出所有运行的容器
♾️ shell 代码:#docker ps (可选参数)
docekr ps #列出正在运行的容器
docker ps -a #列出当前正在运行的容器和历史运行的容器
docker ps -n=? #显示最近创建的容器,?是数字,表示显示几个
docker -p #显示容器编号
#示例
[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker ps -n=1
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2d13e5147554 centos "/bin/bash" 6 minutes ago Exited (0) 4 minutes ago heuristic_tu
[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker ps -n=4
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2d13e5147554 centos "/bin/bash" 6 minutes ago Exited (0) 4 minutes ago heuristic_tu
ff7056f81cfe d1165f221234 "/hello" 25 hours ago Exited (0) 25 hours ago nervous_kalam
删除容器
和前面删除镜像的方式一样,只是镜像是rmi而容器是rm,殊途同归♾️ shell 代码:
docker rm 容器id #删除指定容器,同时如果容器在运行,就不能删除
docker rm -f $(docker ps -aq) #使用递归删除所有容器
docker ps -a -q |xargs docker rm #删除所有容器,也可写作docker ps -aq|xargs docker rm
启动和停止容器
♾️ shell 代码:docker start 容器id #启动容器
docker restart 容器id #重启容器
docker stop 容器id #停止当前运行容器
docker kill 容器id #强制停止当前容器
其他常用命令
后台启动容器
♾️ shell 代码:#docker run -d 镜像名
[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker run -d centos
3c7893d0514ae66e0d31bc9efb725b98504467599376e494dcea47d629a13dbf
[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[root@iZj6c5ctiawsbu90vbskdwZ ~]#
#这里我们通过docker ps 发现容器停止了,那么是怎么一会事,我们说一说。
#docekr 容器在使用后台运行的时候,如果说没有一个前台进程,那么就会自动停止,也就是说,如果要使用后台运行,就必须要有一个前台进程!
查看日志
♾️ shell 代码:docker logs -f -t --tail ?容器id #?表示数字,即你要显示多少条日志,同时-f -t可以写在一起即-tf
docker logs -f t 容器id #显示全部日志
显示容器进程信息
♾️ shell 代码:docker top 容器id
[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker top 1ff8b6186c5f
UID PID PPID C STIME TTY TIME CMD
root 22368 22349 0 11:08 pts/0 00:00:00 /bin/bash
查看镜像元数据
♾️ shell 代码:docker inspect top 容器id
[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
1ff8b6186c5f centos "/bin/bash" 10 seconds ago Up 9 seconds inspiring_thompson
[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker inspect 1ff8b6186c5f
[
{
"Id": "1ff8b6186c5f5d19b715a5c320b7ecb330f9e570e9bba2ff82bce2ceb7344262",
"Created": "2021-07-21T03:08:39.027552726Z",
"Path": "/bin/bash",
"Args": [],
"State": {
"Status": "running",
"Running": true,
"Paused": false,
"Restarting": false,
"OOMKilled": false,
"Dead": false,
"Pid": 22368,
"ExitCode": 0,
"Error": "",
"StartedAt": "2021-07-21T03:08:39.311797803Z",
"FinishedAt": "0001-01-01T00:00:00Z"
},
"Image": "sha256:300e315adb2f96afe5f0b2780b87f28ae95231fe3bdd1e16b9ba606307728f55",
"ResolvConfPath": "/var/lib/docker/containers/1ff8b6186c5f5d19b715a5c320b7ecb330f9e570e9bba2ff82bce2ceb7344262/resolv.conf",
"HostnamePath": "/var/lib/docker/containers/1ff8b6186c5f5d19b715a5c320b7ecb330f9e570e9bba2ff82bce2ceb7344262/hostname",
"HostsPath": "/var/lib/docker/containers/1ff8b6186c5f5d19b715a5c320b7ecb330f9e570e9bba2ff82bce2ceb7344262/hosts",
"LogPath": "/var/lib/docker/containers/1ff8b6186c5f5d19b715a5c320b7ecb330f9e570e9bba2ff82bce2ceb7344262/1ff8b6186c5f5d19b715a5c320b7ecb330f9e570e9bba2ff82bce2ceb7344262-json.log",
"Name": "/inspiring_thompson",
"RestartCount": 0,
"Driver": "overlay2",
"Platform": "linux",
"MountLabel": "",
"ProcessLabel": "",
"AppArmorProfile": "",
"ExecIDs": null,
"HostConfig": {
"Binds": null,
"ContainerIDFile": "",
"LogConfig": {
"Type": "json-file",
"Config": {}
},
"NetworkMode": "default",
"PortBindings": {},
"RestartPolicy": {
"Name": "no",
"MaximumRetryCount": 0
},
"AutoRemove": false,
"VolumeDriver": "",
"VolumesFrom": null,
"CapAdd": null,
"CapDrop": null,
"CgroupnsMode": "host",
"Dns": [],
"DnsOptions": [],
"DnsSearch": [],
"ExtraHosts": null,
"GroupAdd": null,
"IpcMode": "private",
"Cgroup": "",
"Links": null,
"OomScoreAdj": 0,
"PidMode": "",
"Privileged": false,
"PublishAllPorts": false,
"ReadonlyRootfs": false,
"SecurityOpt": null,
"UTSMode": "",
"UsernsMode": "",
"ShmSize": 67108864,
"Runtime": "runc",
"ConsoleSize": [
0,
0
],
"Isolation": "",
"CpuShares": 0,
"Memory": 0,
"NanoCpus": 0,
"CgroupParent": "",
"BlkioWeight": 0,
"BlkioWeightDevice": [],
"BlkioDeviceReadBps": null,
"BlkioDeviceWriteBps": null,
"BlkioDeviceReadIOps": null,
"BlkioDeviceWriteIOps": null,
"CpuPeriod": 0,
"CpuQuota": 0,
"CpuRealtimePeriod": 0,
"CpuRealtimeRuntime": 0,
"CpusetCpus": "",
"CpusetMems": "",
"Devices": [],
"DeviceCgroupRules": null,
"DeviceRequests": null,
"KernelMemory": 0,
"KernelMemoryTCP": 0,
"MemoryReservation": 0,
"MemorySwap": 0,
"MemorySwappiness": null,
"OomKillDisable": false,
"PidsLimit": null,
"Ulimits": null,
"CpuCount": 0,
"CpuPercent": 0,
"IOMaximumIOps": 0,
"IOMaximumBandwidth": 0,
"MaskedPaths": [
"/proc/asound",
"/proc/acpi",
"/proc/kcore",
"/proc/keys",
"/proc/latency_stats",
"/proc/timer_list",
"/proc/timer_stats",
"/proc/sched_debug",
"/proc/scsi",
"/sys/firmware"
],
"ReadonlyPaths": [
"/proc/bus",
"/proc/fs",
"/proc/irq",
"/proc/sys",
"/proc/sysrq-trigger"
]
},
"GraphDriver": {
"Data": {
"LowerDir": "/var/lib/docker/overlay2/f374005ba37d8dd511a5663780d1a6d9f73721853d0f865f93fa06c294099b6e-init/diff:/var/lib/docker/overlay2/95fb52765b6ea97468e0c38889f47d9e3c95d2e69d556c18798f00ebb3e2cfb1/diff",
"MergedDir": "/var/lib/docker/overlay2/f374005ba37d8dd511a5663780d1a6d9f73721853d0f865f93fa06c294099b6e/merged",
"UpperDir": "/var/lib/docker/overlay2/f374005ba37d8dd511a5663780d1a6d9f73721853d0f865f93fa06c294099b6e/diff",
"WorkDir": "/var/lib/docker/overlay2/f374005ba37d8dd511a5663780d1a6d9f73721853d0f865f93fa06c294099b6e/work"
},
"Name": "overlay2"
},
"Mounts": [],
"Config": {
"Hostname": "1ff8b6186c5f",
"Domainname": "",
"User": "",
"AttachStdin": true,
"AttachStdout": true,
"AttachStderr": true,
"Tty": true,
"OpenStdin": true,
"StdinOnce": true,
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
],
"Cmd": [
"/bin/bash"
],
"Image": "centos",
"Volumes": null,
"WorkingDir": "",
"Entrypoint": null,
"OnBuild": null,
"Labels": {
"org.label-schema.build-date": "20201204",
"org.label-schema.license": "GPLv2",
"org.label-schema.name": "CentOS Base Image",
"org.label-schema.schema-version": "1.0",
"org.label-schema.vendor": "CentOS"
}
},
"NetworkSettings": {
"Bridge": "",
"SandboxID": "236a57971cd0b33ec1fd5b3c8cd725fabd85aef3a796de461a699c42b6e289f6",
"HairpinMode": false,
"LinkLocalIPv6Address": "",
"LinkLocalIPv6PrefixLen": 0,
"Ports": {},
"SandboxKey": "/var/run/docker/netns/236a57971cd0",
"SecondaryIPAddresses": null,
"SecondaryIPv6Addresses": null,
"EndpointID": "03ed818c13a101bd6254b5e5c18ede6f9c776efb2e65ac382f711b8f8b265b2b",
"Gateway": "172.17.0.1",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"IPAddress": "172.17.0.2",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"MacAddress": "02:42:ac:11:00:02",
"Networks": {
"bridge": {
"IPAMConfig": null,
"Links": null,
"Aliases": null,
"NetworkID": "3be7a57080be0d228e4f459c30ed8bc85ab61b84ac10ddbeaa546ad97f294539",
"EndpointID": "03ed818c13a101bd6254b5e5c18ede6f9c776efb2e65ac382f711b8f8b265b2b",
"Gateway": "172.17.0.1",
"IPAddress": "172.17.0.2",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"MacAddress": "02:42:ac:11:00:02",
"DriverOpts": null
}
}
}
}
]
进入当前正在运行的容器
我们通常都是通过后台方式运行,需要进入容器修改配置信息♾️ shell 代码:
#方式一
docker exec -it 容器id BashShell
[root@jiusheng]# docker exec -it 1ff8b6186c5f /bin/bash
[root@1ff8b6186c5f /]# ls
bin etc lib lost+found mnt proc run srv tmp var
dev home lib64 media opt root sbin sys usr
#方式二
docker attach 容器id
[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker attach 1ff8b6186c5f
[root@1ff8b6186c5f /]#
#区别
docker exec 进入容器后开启新的终端
docker attach 进入容器正在执行的终端,不会启动新终端
从容器拷贝数据到本机
docker cp 容器id:容器内路径 目的路径♾️ shell 代码:
#进入容器内部
[root@1ff8b6186c5f /]# cd /home
[root@1ff8b6186c5f home]# ls
#在容器内部新建一个文件
[root@1ff8b6186c5f home]# touch jiusheng.np
[root@1ff8b6186c5f home]# exit
exit
[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
1ff8b6186c5f centos "/bin/bash" 3 hours ago Exited (0) 16 seconds ago inspiring_thompson
3c7893d0514a centos "/bin/bash" 3 hours ago Exited (0) 3 hours ago clever_lalande
#把文件拷贝到本机
[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker cp 1ff8b6186c5f:/home/jiusheng.np /home
[root@iZj6c5ctiawsbu90vbskdwZ ~]# cd /home
[root@iZj6c5ctiawsbu90vbskdwZ home]# ls
admin jiusheng.np
#我们可以卡看到哈,在容器里面建立的jiusheng.np,我们已经复制到了本机的home目录里面。
小结
勤能补拙,温故而知新
attach Attach to a running container #当前 shell 下 attach 连接指定运行镜像
build Build an image from a Dockerfile #通过 Dockerfile 定制镜像
commit create a new image from a container changes #提交当前容器为新的镜像
cp copy files/folders from the containers filesystem to the host path #从容器中拷贝指定文件或者目录到宿主机中
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 an existing container #在已存在的容器上运行命令
export Stream the contents of a container as a tar archive #导出容器的内容流作为一个 tar 归档文件[对应import ]
history Show the history of an image #展示一个镜像形成历史
images List images # 列出系统当前镜像
import create a new filesystem image from the contents of a tarball #从tar包中的内容创建一个新的文件系统映像[对应export]
info Display system-wide information # 显示系统相关信息
inspect Return low-level information on a container #查看容器详细信息
kill Kill a running container #kill 指定 docker 容器
load Load an image from a tar archive # 从一个 tar 包中加载一个镜像[对应 save]
login Register or Login to the docker registry server # 注册或者登陆一个 docker 源服务器
logout Log out from a Docker registry server # 从当前 Docker registry 退出
logs Fetch the logs of a container #输出当前容器日志信息
port Lookup the public-facing port which is NAT-ed to PRIVATE_PORT #查看映射端口对应的容器内部源端
pause pause all processes within a container #暂停容器
ps List containers #列出容器列表
pull the docker registry server #从docker镜像源服务器拉取指定镜像
push Push an image or a repository to the docker registry server # 推送指定镜像或者库镜像至docker源服务器
restart Restart a running container #重启运行的容器
rm Remove one or more containers # 移除一个或者多个容器
rmi Remove one or more images #移除一个或多个镜像[无容器使用该镜像才可删除,否则需删除相关容器才可继续或 -f 强制删除]
run Run a command in a new container #创建一个新的容器并运行一个命令
save Save an image to a tar archive # 保存一个镜像为一个 tar 包[对应 load]
search Search for an image on the Docker Hub #在 docker hub 中搜索镜像
start Start a stopped containers # 启动容器
stop Stop a running containers #停止容器
tag Tag an image into a repository #给源中镜像打标签
top Lookup the running processes of a container #查看容器中运行的进程信息
unpause Unpause a paused container # 取消暂停容器
version Show the docker version information #查看 docker 版本号
wait Block until a container stops, then print its exit code #截取容器停止时的退出状态值
格式
♾️ shell 代码:# 1. 拉取镜像到本地
docker pull 镜像名称[:tag]
# 举个例子 tomcat
docker pull daocloud.io/library/tomcat:8.5.15-jre8
# 2. 查看全部本地的镜像
docker images
# 3. 删除本地镜像
docker rmi 镜像的标识
# 4. 镜像的导入导出(不规范)
# 将本地的镜像导出
docker save -o 导出的路径 镜像id
# 加载本地的镜像文件
docker load -i 镜像文件
# 修改镜像名称
docker tag 镜像id 新镜像名称:版本
# 1. 运行容器
# 简单操作
docker run 镜像的标识|镜像名称[tag]
# 常用的参数
docker run -d -p 宿主机端口:容器端口 --name 容器名称 镜像的标识|镜像名称[tag]
# -d: 代表后台运行容器
# -p: 宿主机端口:容器端口: 为了映射当前Linux的端口和容器的端口
# --name 容器名称: 指定容器的名称
# 2. 查看正在运行的容器
docker ps [OPTIONS]
# OPTIONS说明:
# -a: 代表查看全部的容器,包括没有运行
# -q: 只查看容器的标识
# -f: 根据条件过滤显示的内容
# --format: 指定返回值的模板文件
# -l: 显示最近创建的容器
# -n: 列出最近创建的n个容器
# --no-trunc: 不截断输出
# -s: 显示总的文件大小
# 3. 查看容器的日志
docker logs -f 容器id
# -f: 可以滚动查看日志的最后几行
# 4. 进入到容器内部
docker exec -it 容器id bash
# 5. 删除容器(删除容器前,需要先停止容器)
docker stop 容器id
# 停止指定的容器
docker stop $(docker ps -qa)
# 停止全部容器
docker rm 镜像id
# 删除指定容器
docker rm $(docker ps -qa)
# 删除全部容器
#6. 启动容器
docker start 容器id
作业练习
安装Nginx
安装nginx
♾️ shell 代码:docker search nginx
下载镜像
♾️ shell 代码:docker pull nginx
运行镜像
♾️ shell 代码:# -d 后台运行 # --name 给容器命名 # -p 端口映射,本机端口:容器内部端口 docker run -d --name jiusheng -p 520:80 nginx #查看是否启动 [root@iZj6c5ctiawsbu90vbskdwZ ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 82e88fd7529c nginx "/docker-entrypoint.…" 12 seconds ago Up 10 seconds 0.0.0.0:520->80/tcp jiusheng #查看端口是否连通 [root@iZj6c5ctiawsbu90vbskdwZ ~]# curl localhost:520 <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> <style> body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } </style> </head> <body> <h1>Welcome to nginx!</h1> <p>If you see this page, the nginx web server is successfully installed and working. Further configuration is required.</p> <p>For online documentation and support please refer to <a href="http://nginx.org/">nginx.org</a>.<br/> Commercial support is available at <a href="http://nginx.com/">nginx.com</a>.</p> <p><em>Thank you for using nginx.</em></p> </body> </html>
进入容器
♾️ smalltalk 代码:docker exec -it jiusheng /bin/bach
- 端口映射概念
安装tomcat
注意,在官网上的使用方法如下:♾️ shell 代码:
docker run -it --rm tomcat:9.0
这里我们不推荐,我们一般是使用后台启动,停止了容器后,还可以查找到, 但是docker run -it --rm ,使用之后就会直接删除,查找不到,也就是说是一个即用即删的,多用于测试!
- 搜索tomcat镜像
docker searce tomcat
- 下载tomcat
docker pull tomcat
- 启动运行
docker run -d -p 250:8080 --name tomcat01 tomcat
- 测试访问
curl localhost:250
访问ip:250
- 访问的通,没有出现想要的页面
#进入容器
docker exec -it tomcat01 /bin/bash
#发现少了命令,同时没有web。
#原因:默认最小安装,剔除了不必要的东西,保证最小化运行环境。
#解决方法
cp -r webapps.dist/* webapps
#之后就可以访问量
部署elasticsearch简称es+kibana♾️ shell 代码:
#官方命令
#--net somenetwork 网络配置
#"discovery.type=single-node" 集群配置,默认单节点
docker run -d --name elasticsearch --net somenetwork -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:tag
#我们做一些修改
docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e EC_JAVA_OPTS="=-Xms64m -Xm512m" elasticsearch:7.6.2
#去掉了网络服务
#改了名字
#增加了环境限制,别问,问就是这个非常耗内存,我的机子托不动,然后指定了版本号
docker run -d --name=es2 -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms64m -Xmx512m" elasticsearch:7.6.2
- 查看容器占用内存
docker stats 容器id
- 检查是否启动成功
curl localhost:9200
#参考
[root@iZj6c5ctiawsbu90vbskdwZ ~]# curl localhost:9200
{
"name" : "62ee34017bec",
"cluster_name" : "docker-cluster",
"cluster_uuid" : "3OGmDOBLSOOYOeQQ23F7dQ",
"version" : {
"number" : "7.6.2",
"build_flavor" : "default",
"build_type" : "docker",
"build_hash" : "ef48eb35cf30adf4db14086e8aabd07ef6fb113f",
"build_date" : "2020-03-26T06:34:37.794943Z",
"build_snapshot" : false,
"lucene_version" : "8.4.0",
"minimum_wire_compatibility_version" : "6.8.0",
"minimum_index_compatibility_version" : "6.0.0-beta1"
},
"tagline" : "You Know, for Search"
}
部署可视化面板
Portainer
这里需要主要的是,我们安装ce版本即可,因为这是开源切免费的!
官网地址:
https://documentation.portainer.io/v2.0/deploy/ceinstalldocker/
Portainer 服务器部署♾️ shell 代码:
docker volume create portainer_data
docker run -d -p 8000:8000 -p 9000:9000 --name=portainer --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer-ce
Portainer 仅代理部署♾️ shell 代码:
docker run -d -p 9001:9001 --name portainer_agent --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v /var/lib/docker/volumes:/var/lib/docker/volumes portainer/agent
♾️ shell 代码:#查看是否启动成功
[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8b100ad7b90f portainer/agent "./agent" 24 seconds ago Up 23 seconds 0.0.0.0:9001->9001/tcp portainer_agent
访问测试
这是一个登录界面,在这里我们需要建立管理员角色
创建成功之后,我们进入后台界面
这样就完安装完成了,我们也不使用,就简单的了解就好了
镜像讲解
Docker镜像加载原理
镜像是什么
镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需的所有内容,包括代码、运行时、库、环境变量和配置文件
UnionFS(联合文件系统)
- Union文件系统(UnionFS)是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtual filesystem)。Union 文件系统是 Docker 镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。
- 特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件,系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录
Docker镜像加载原理
- docker的镜像实际上由一层一层的文件系统组成,这种层级的文件系统UnionFS。bootfs(boot file system)主要包含bootloader和kernel, bootloader主要是引导加载kernel, Linux刚启动时会加载bootfs文件系统,在Docker镜像的最底层是bootfs。
这一层与我们典型的Linux/Unix系统是一样的,包含boot加载器和内核。当boot加载完成之后整个内核就都在内存中了,此时内存的使用权已由bootfs转交给内核,此时系统也会卸载bootfs。 rootfs (root file system) ,在bootfs之上。包含的就是典型 Linux 系统中的 /dev, /proc, /bin, /etc 等标准目录和文件。rootfs就是各种不同的操作系统发行版,比如Ubuntu,Centos等等
- 平时我们安装进虚拟机的 CentOS 都是好几个 G ,为什么 Docker 这里才 200M ?
- 对于一个精简的OS,rootfs 可以很小,只需要包含最基本的命令,工具和程序库就可以了,因为底层直接用Host的kernel,自己只需要提供rootfs就可以了。由此可见对于不同的linux发行版, bootfs基本是一致的, rootfs会有差别, 因此不同的发行版可以公用bootfs。
分层理解
- 我们可以去下载一个镜像,注意观察下载的日志输出,可以看到是一层一层的在下载!
为什么Docker镜像要采用这种分层的结构呢?
- 最大的好处,我觉得莫过于是资源共享了!比如有多个镜像都从相同的Base镜像构建而来,那么宿主机只需在磁盘上保留一份base镜像,同时内存中也只需要加载一份base镜像,这样就可以为所有的容器服务了,而且镜像的每一层都可以被共享。查看镜像分层的方式可以通过 docker image inspect 命令!
所有的 Docker 镜像都起始于一个基础镜像层,当进行修改或增加新的内容时,就会在当前镜像层之上,创建新的镜像层。
举一个简单的例子,假如基于 Ubuntu Linux 16.04 创建一个新的镜像,这就是新镜像的第一层;如果在该镜像中添加 Python包,就会在基础镜像层之上创建第二个镜像层;如果继续添加一个安全补丁,就会创建第三个镜像层。该镜像当前已经包含 3 个镜像层,如下图所示(这只是一个用于演示的很简单的例子
在添加额外的镜像层的同时,镜像始终保持是当前所有镜像的组合,理解这一点非常重要。下图中举了一个简单的例子,每个镜像层包含 3 个文件,而镜像包含了来自两个镜像层的 6 个文件。
上图中的镜像层跟之前图中的略有区别,主要目的是便于展示文件。
下图中展示了一个稍微复杂的三层镜像,在外部看来整个镜像只有 6 个文件,这是因为最上层中的文件7 是文件 5 的一个更新版本。
这种情况下,上层镜像层中的文件覆盖了底层镜像层中的文件。这样就使得文件的更新版本作为一个新镜像层添加到镜像当中。
Docker 通过存储引擎(新版本采用快照机制)的方式来实现镜像层堆栈,并保证多镜像层对外展示为统一的文件系统。
Linux 上可用的存储引擎有 AUFS、Overlay2、Device Mapper、Btrfs 以及 ZFS。顾名思义,每种存储引擎都基于 Linux 中对应的文件系统或者块设备技术,并且每种存储引擎都有其独有的性能特点。
Docker 在 Windows 上仅支持 windowsfilter 一种存储引擎,该引擎基于 NTFS 文件系统之上实现了分层和 CoW[1]。下图展示了与系统显示相同的三层镜像。所有镜像层堆叠并合并,对外提供统一的视图
特点
Docker镜像都是只读的,当容器启动时,一个新的可写层被加载到镜像的顶部!
这一层就是我们通常说的容器层,容器之下的都叫镜像层
commit
♾️ shell 代码:commit的作用相当于快照
提交镜像
docker commit -m="提交信息" -a="作者" 容器id 目标镜像名:[tag]
测试
启动tomcat
♾️ shell 代码:docker run -it -p 432:8080 comcat
进入comcat
♾️ shell 代码:docker exec -it 容器id /bin/bash
拷贝数据
♾️ shell 代码:cp -r webapps.dist/* webapps
访问地址是否修改成功
♾️ shell 代码:http://47.243.161.30:432/
退出容器并提交新的修改
♾️ shell 代码:#退出容器 exit #提交修改 docker commit -a="jiusheng" -m="webapps" 0cee6cf8bd57 comcat02:1.1
查看是否生成成功
♾️ shell 代码:docker images comcat02 1.1 31ea9dda1fda 8 seconds ago 677MB portainer/portainer-ce latest 865cf8021627 2 weeks ago 210MB portainer/agent latest 3cdf856343c6 2 weeks ago 138MB nginx latest 4cdc5dd7eaad 2 weeks ago 133MB tomcat latest 36ef696ea43d 3 weeks ago 667MB centos latest 300e315adb2f 7 months ago 209MB kibana 7.6.2 f70986bc5191 16 months ago 1.01GB elasticsearch 7.6.2 f29a1ee41030 16 months ago 791MB
容器数据卷
docker数据卷概念
Docker的理念是:将运用与运行的环境打包形成容器运行 ,运行可以伴随着容器。
Docker容器产生的数据,如果不通过docker commit生成新的镜像,使得数据做为镜像的一部分保存下来,那么当容器删除后,数据自然也就没有了。
所以我们希望:数据可以持久化、容器之间(甚至容器与宿主机之间)可以数据共享。为了能保存数据可以在docker中使用卷。卷的设计目的就是数据的持久化,完全独立于容器的生存周期,因此Docker不会在容器删除时删除其挂载的数据卷。
卷就是目录或文件,存在于一个或多个容器中,由docker挂载到容器,但不属于联合文件系统,因此能够绕过Union File System提供一些用于持续存储或共享数据的特性:
- 数据卷可在容器之间共享或重用数据
- 卷中的更改可以直接生效
- 数据卷中的更改不会包含在镜像的更新中
- 数据卷的生命周期一直持续到没有容器使用它为止
为什么使用数据卷
Docker的镜像是由一系列的只读层组合而来,当启动一个容器的时候,Docker加载镜像的所有只读层,并在最上层加入一个读写层。这个设计使得Docker可以提高镜像构建、存储和分发的效率,节省了时间和存储空间,然而也存在如下问题。
容器中的文件在宿主机上存在形式复杂,不能在宿主机上很方便的对容器中的文件进行访问
- 多个容器之间的数据无法共享
- 当删除容器时,容器产生的数据将丢失
为了解决这些问题,Docker引入了数据卷(volume)机制。volume是存在一个或多个容器中的特定文件或文件夹,这个目录能够独立于联合文件系统的形式在宿主机中存在,并为数据的共享与持久提供一下便利。
- volume在容器创建时就初始化,在容器运行时就可以使用其中的文件
- volume能在不同的容器之间共享和重用
- volume中的数据的操作会马上生效
- volume中数据操作不会影响到镜像本身
- volume的生存周期独立于容器的生存周期,即使删除容器,volume仍然会存在,没有任何容器使用的volume也不会被Docker删除
volume命令
了解volume的命令
- 使用帮助文档查看命令
docker volume --help
- 参数说明
create #创建卷
inspect #显示一个或多个数据卷的详细信息
ls #列出所有卷
prune #删除所有未使用的数据卷
rm #删除一个或多个卷
- 创建一个数据卷
♾️ shell 代码:基本格式如下:
docker volume create 名字
docker volume create jiu
此时,数据卷默认会放到/var/lib/docker/volumes路径下,会发现所新建的数据卷位置,查看命令如下:
\## 参数可以为数字“1”,字母L:大小写均可,但效果不一样
ls -1 /var/lib/docker/volumes为什么会在这里,我们可以来看一下docker的文件目录:
docker的默认目录为/var/lib/docker/
里面的结构如下
├── containers #用来存储容器信息
├── image #用来存储镜像中间件及本身信息,大小,依赖信息
│ └── overlay2
│ ├── distribution
│ ├── imagedb
│ │ ├── content
│ │ │ └── sha256
│ │ └── metadata
│ │ └── sha256
│ ├── layerdb
│ └── repositories.json
├── network #网络信息
│ └── files
│ └── local-kv.db
├── overlay2 #存放镜像
│ └── l
├── plugins
│ ├── storage
│ │ └── blobs
│ │ └── tmp
│ └── tmp
├── swarm
├── tmp #docker临时目录
├── trust #docker信任目录
└── volumes #docker卷目录
└── metadata.db
- 列出所有数据卷
docker volume ls
- 查询数据卷信息
♾️ shell 代码:格式:
docker volume inspect 数据卷名
docker volume inspect jiu
[root@iZj6c5ctiawsbu90vbskdwZ docker]# docker volume inspect jiu
[
{
"CreatedAt": "2021-07-27T16:49:41+08:00",
"Driver": "local",
"Labels": {},
"Mountpoint": "/var/lib/docker/volumes/jiu/_data", #存放位置
"Name": "jiu", #数据卷名
"Options": {},
"Scope": "local"
}
]
- 删除一个数据卷
♾️ shell 代码:格式:
docker volume rm 数据卷名
docker volume rm jiu
[root@iZj6c5ctiawsbu90vbskdwZ docker]# docker volume ls
DRIVER VOLUME NAME
local jiu
[root@iZj6c5ctiawsbu90vbskdwZ docker]# docker volume rm jiu
jiu
[root@iZj6c5ctiawsbu90vbskdwZ docker]# docker volume ls
DRIVER VOLUME NAME
#可以看到已经删除成功了
- 删除所有没有使用的数据卷
♾️ shelll 代码:格式:
docker volume prune
docker volume prune
#这里我们提前创建了一些数据卷
[root@iZj6c5ctiawsbu90vbskdwZ docker]# docker volume prune
WARNING! This will remove all local volumes not used by at least one container.
Are you sure you want to continue? [y/N] y
Deleted Volumes:
jiu
sheng
hahha
Total reclaimed space: 0B
#可以看到没有使用的数据均已经全部删除完毕了
数据卷的使用
数据卷目前有两种方式来进行使用,一种是直接通过命令来进行挂载,一种是通过DockerFile来进行添加
命令格式:
docker run -it -v 主机目录:容器内目录
测试
- 启动并挂载数据卷
docker run -it -v /home/ceshi:/home centos /bin/bash
- 查看是否生成挂载目录测试,并成功挂载
[root@iZj6c5ctiawsbu90vbskdwZ /]# cd /home/
[root@iZj6c5ctiawsbu90vbskdwZ home]# ls
admin ceshi
[root@iZj6c5ctiawsbu90vbskdwZ home]#
[root@iZj6c5ctiawsbu90vbskdwZ ceshi]# docker inspect 1795f7f64501
[
{
"Id": "1795f7f64501188c8e74a8f9f5b2fb8703a84f0d7b36606f3f98ce2c06b93f3f",
"Created": "2021-07-27T09:33:28.066660046Z",
"Path": "/bin/bash",
"Args": [],
"State": {
"Status": "running",
"Running": true,
"Paused": false,
"Restarting": false,
"OOMKilled": false,
"Dead": false,
"Pid": 8000,
"ExitCode": 0,
"Error": "",
"StartedAt": "2021-07-27T09:33:28.409923354Z",
"FinishedAt": "0001-01-01T00:00:00Z"
},
"Image": "sha256:300e315adb2f96afe5f0b2780b87f28ae95231fe3bdd1e16b9ba606307728f55",
"ResolvConfPath": "/var/lib/docker/containers/1795f7f64501188c8e74a8f9f5b2fb8703a84f0d7b36606f3f98ce2c06b93f3f/resolv.conf",
"HostnamePath": "/var/lib/docker/containers/1795f7f64501188c8e74a8f9f5b2fb8703a84f0d7b36606f3f98ce2c06b93f3f/hostname",
"HostsPath": "/var/lib/docker/containers/1795f7f64501188c8e74a8f9f5b2fb8703a84f0d7b36606f3f98ce2c06b93f3f/hosts",
"LogPath": "/var/lib/docker/containers/1795f7f64501188c8e74a8f9f5b2fb8703a84f0d7b36606f3f98ce2c06b93f3f/1795f7f64501188c8e74a8f9f5b2fb8703a84f0d7b36606f3f98ce2c06b93f3f-json.log",
"Name": "/gallant_sanderson",
"RestartCount": 0,
"Driver": "overlay2",
"Platform": "linux",
"MountLabel": "",
"ProcessLabel": "",
"AppArmorProfile": "",
"ExecIDs": null,
"HostConfig": {
"Binds": [
"/home/ceshi:/home"
],
"ContainerIDFile": "",
"LogConfig": {
"Type": "json-file",
"Config": {}
},
"NetworkMode": "default",
"PortBindings": {},
"RestartPolicy": {
"Name": "no",
"MaximumRetryCount": 0
},
"AutoRemove": false,
"VolumeDriver": "",
"VolumesFrom": null,
"CapAdd": null,
"CapDrop": null,
"CgroupnsMode": "host",
"Dns": [],
"DnsOptions": [],
"DnsSearch": [],
"ExtraHosts": null,
"GroupAdd": null,
"IpcMode": "private",
"Cgroup": "",
"Links": null,
"OomScoreAdj": 0,
"PidMode": "",
"Privileged": false,
"PublishAllPorts": false,
"ReadonlyRootfs": false,
"SecurityOpt": null,
"UTSMode": "",
"UsernsMode": "",
"ShmSize": 67108864,
"Runtime": "runc",
"ConsoleSize": [
0,
0
],
"Isolation": "",
"CpuShares": 0,
"Memory": 0,
"NanoCpus": 0,
"CgroupParent": "",
"BlkioWeight": 0,
"BlkioWeightDevice": [],
"BlkioDeviceReadBps": null,
"BlkioDeviceWriteBps": null,
"BlkioDeviceReadIOps": null,
"BlkioDeviceWriteIOps": null,
"CpuPeriod": 0,
"CpuQuota": 0,
"CpuRealtimePeriod": 0,
"CpuRealtimeRuntime": 0,
"CpusetCpus": "",
"CpusetMems": "",
"Devices": [],
"DeviceCgroupRules": null,
"DeviceRequests": null,
"KernelMemory": 0,
"KernelMemoryTCP": 0,
"MemoryReservation": 0,
"MemorySwap": 0,
"MemorySwappiness": null,
"OomKillDisable": false,
"PidsLimit": null,
"Ulimits": null,
"CpuCount": 0,
"CpuPercent": 0,
"IOMaximumIOps": 0,
"IOMaximumBandwidth": 0,
"MaskedPaths": [
"/proc/asound",
"/proc/acpi",
"/proc/kcore",
"/proc/keys",
"/proc/latency_stats",
"/proc/timer_list",
"/proc/timer_stats",
"/proc/sched_debug",
"/proc/scsi",
"/sys/firmware"
],
"ReadonlyPaths": [
"/proc/bus",
"/proc/fs",
"/proc/irq",
"/proc/sys",
"/proc/sysrq-trigger"
]
},
"GraphDriver": {
"Data": {
"LowerDir": "/var/lib/docker/overlay2/9952b87bf9c7b7b84fbbdb2ac08fdc7ceb96b8cdf21c4f2d1d2f49bd8595ee1f-init/diff:/var/lib/docker/overlay2/95fb52765b6ea97468e0c38889f47d9e3c95d2e69d556c18798f00ebb3e2cfb1/diff",
"MergedDir": "/var/lib/docker/overlay2/9952b87bf9c7b7b84fbbdb2ac08fdc7ceb96b8cdf21c4f2d1d2f49bd8595ee1f/merged",
"UpperDir": "/var/lib/docker/overlay2/9952b87bf9c7b7b84fbbdb2ac08fdc7ceb96b8cdf21c4f2d1d2f49bd8595ee1f/diff",
"WorkDir": "/var/lib/docker/overlay2/9952b87bf9c7b7b84fbbdb2ac08fdc7ceb96b8cdf21c4f2d1d2f49bd8595ee1f/work"
},
"Name": "overlay2"
},
"Mounts": [
{
"Type": "bind",
"Source": "/home/ceshi", #我们可以看到这里是挂载上去了的,那我们接着来测试
"Destination": "/home", #容器内的地址
"Mode": "",
"RW": true,
"Propagation": "rprivate"
}
],
"Config": {
"Hostname": "1795f7f64501",
"Domainname": "",
"User": "",
"AttachStdin": true,
"AttachStdout": true,
"AttachStderr": true,
"Tty": true,
"OpenStdin": true,
"StdinOnce": true,
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
],
"Cmd": [
"/bin/bash"
],
"Image": "centos",
"Volumes": null,
"WorkingDir": "",
"Entrypoint": null,
"OnBuild": null,
"Labels": {
"org.label-schema.build-date": "20201204",
"org.label-schema.license": "GPLv2",
"org.label-schema.name": "CentOS Base Image",
"org.label-schema.schema-version": "1.0",
"org.label-schema.vendor": "CentOS"
}
},
"NetworkSettings": {
"Bridge": "",
"SandboxID": "c5803986c1107b2e97d534aab5c2725f355b7cef1c171afd8486f72d0b83a382",
"HairpinMode": false,
"LinkLocalIPv6Address": "",
"LinkLocalIPv6PrefixLen": 0,
"Ports": {},
"SandboxKey": "/var/run/docker/netns/c5803986c110",
"SecondaryIPAddresses": null,
"SecondaryIPv6Addresses": null,
"EndpointID": "f6f8cedcc0ad532f2c01910f84e3436c1c33ec8aa0d2e47236de75bde44c8384",
"Gateway": "172.17.0.1",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"IPAddress": "172.17.0.2",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"MacAddress": "02:42:ac:11:00:02",
"Networks": {
"bridge": {
"IPAMConfig": null,
"Links": null,
"Aliases": null,
"NetworkID": "3be7a57080be0d228e4f459c30ed8bc85ab61b84ac10ddbeaa546ad97f294539",
"EndpointID": "f6f8cedcc0ad532f2c01910f84e3436c1c33ec8aa0d2e47236de75bde44c8384",
"Gateway": "172.17.0.1",
"IPAddress": "172.17.0.2",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"MacAddress": "02:42:ac:11:00:02",
"DriverOpts": null
}
}
}
}
]
- 在本机添加文件
#生成一个jiusheng.666的文件
[root@iZj6c5ctiawsbu90vbskdwZ ceshi]# touch jiusheng.666
[root@iZj6c5ctiawsbu90vbskdwZ ceshi]# ls
jiusheng.666
- 到容器里面查看是否同步
#可以看到是已经同步的了
[root@1795f7f64501 /]# cd /home/
[root@1795f7f64501 home]# ls
jiusheng.666
- 在容器内删除文件
[root@1795f7f64501 home]# rm jiusheng.666
rm: remove regular empty file 'jiusheng.666'? y
[root@1795f7f64501 home]#
#这里我们在容器里面已经吧文件jiusheng.666删除掉了,我们去宿主机看看文件还在不在
[root@iZj6c5ctiawsbu90vbskdwZ ceshi]# ls
[root@iZj6c5ctiawsbu90vbskdwZ ceshi]#
#可以看到是没有任何文件的,也就是说这里目录下的文件是双向绑定的,同时,你停止或者删除容器,里面的内容也是不会变得,出给你认为的去修改或者删除!
挂载之后的文件就是共享,同时不管你删除容器还是停止容器,映射出来的文件不会随之消失!
这里删除或者停止容器的测试就不在赘述了。
拓展
♾️ shell 代码:我们在实际使用的过程中,会发现有一些的命令会多一个ro 或者rw
这个是读取权限:
ro 只读
rw 可读可写
不设置的话,默认.rw
docker run -it -v /myDataVolume:/dataVolumeContainer:ro centos
-v #代表数据卷
/myDataVolume #宿主机绝对路径目录
:/dataVolumeContainer #容器内目录
centos #镜像名
:ro #设置权限为只读
安装MySQL
- 下载mysql
docker pull mysql:5.6
- 运行容器并进行数据挂载
#这是官方给的方式,我们进行就该
#my-secret-pw -d 表示密码,进行修改
#-e 是环境变量
docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag
♾️ shell 代码:docker run -p 3306:3306 --name mymysql -v $PWD/conf:/etc/mysql/conf.d -v $PWD/logs:/logs -v $PWD/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7
参数解释:
-p 3306:3306:将容器的 3306 端口映射到主机的 3306 端口。
-v $PWD/conf:/etc/mysql/conf.d:将主机当前目录下的 conf/my.cnf 挂载到容器的 /etc/mysql/my.cnf。
-v $PWD/logs:/logs:将主机当前目录下的 logs 目录挂载到容器的 /logs。
-v $PWD/data:/var/lib/mysql :将主机当前目录下的data目录挂载到容器的 /var/lib/mysql 。
-e MYSQL_ROOT_PASSWORD=123456:初始化 root 用户的密码。
- 连接看测试
可以看到连接成功,下面我们创建一个表来测试
这个时候我们来数据是否同步
- 我们停止掉原来的数据库,同时新开一个数据库
docker run -p 3307:3306 --name mysql01 -v $PWD/conf:/etc/mysql/conf.d -v $PWD/logs:/logs -v $PWD/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7
我们来进行连接
我们之前创建的数据都还在
至此,我们可以很明确的知道,数据卷的使用,可以实现数据的持久化。不再一删除容器就什么都没有了!
具名和匿名挂载
什么是具名挂载和匿名挂载?
我们前面挂载数据卷的时候是通过 -v 主机路径:容器内路径 ,来进行挂载的,那么我们不指定主机的挂载路径只指定容器内路径,-v 容器内路径 那么这个就是匿名挂载, 反之如果我们吧主机路径变成别名,那么就是具名挂载在,比如: -v jiusheng:容器内路径
匿名挂载
- 使用匿名挂载启动nginx
docker run -d -P --name nginx01 -v /etc/nginx nginx
参数解读:
-P 随机端口
-v 匿名挂载会随机生成挂载路径
- 使用volume查看数据卷
docker volume ls
[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker volume ls
DRIVER VOLUME NAME
local 0ba2accbb52f84f4ddd1b92995db0ce4e8adbb3f710595f26823f9f01f014c65
local 8f054507bd037b086e742d764f415df0fcbb08e7d1e71f3c83c1e112f7c28ca1
local 81e46324431241ff7b95a6cceb4b5dd85d9b9eefb03aa55d46f153b101a8502f
local 82a3da984765cbbdb73797cec9038650e035a2511a07479370587787fc331501
local 53050314ad0cf8d879280a1c1df3a587f497ae93315da31cc5d97ae7a0907f3c
local bc56b1d4485fb0a171f5807204408a6257109311e37365bbfd79387afc940cb9
local cb7e41c8d674d05d355c10b0a7101bf7569500b78c38d8f50ca6f87ed5c265d6
local f4785b207baa99a0214b40816dcc51e265a5ea5a66e4f55a1ab1b6d286ab47f9
- 查看匿名挂载路径
docker volume inspect
[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker volume inspect f4785b207baa99a0214b40816dcc51e265a5ea5a66e4f55a1ab1b6d286ab47f9
[
{
"CreatedAt": "2021-07-29T08:56:05+08:00",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/f4785b207baa99a0214b40816dcc51e265a5ea5a66e4f55a1ab1b6d286ab47f9/_data",
"Name": "f4785b207baa99a0214b40816dcc51e265a5ea5a66e4f55a1ab1b6d286ab47f9",
"Options": null,
"Scope": "local"
}
]
具名挂载
- 使用具名挂载nginx
docker run -d -P --name nginx02 -v jumingguazai:/etc/nginx nginx
- 查看数据卷
docker volume ls
[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker volume ls
DRIVER VOLUME NAME
local jumingguazai
- 查看具名挂载地址
docker volume inspect jumingguazai
[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker volume inspect jumingguazai
[
{
"CreatedAt": "2021-07-29T10:46:44+08:00",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/jumingguazai/_data",
"Name": "jumingguazai",
"Options": null,
"Scope": "local"
}
]
我们可以看到,不管是匿名挂载还是具名挂载,默认的挂载目录地址都是在/var/lib/docker/volumes/xxx/_data
我们通过具名挂载可以方便的找到我们挂载的卷,所以大多数情况也就使用具名挂载
区分挂载类型
-v 容器内路径 | 匿名挂载 |
---|---|
-v 卷名:容器内路径 | 具名挂载 |
-v /宿主机路径:容器内路径 | 指定路径挂载 ,注意有/ |
dockerfile挂载数据卷
编写脚本♾️ shell 代码:
FROM centos
VOLUME ["jiusheng01","jiusheng02"]
CMD echo "-------jiushengzuishuai------"
CMD /bin/bash
基本格式
♾️ shell 代码:docker build -f 脚本名 -t 镜像名 .
创建一个自己的镜像
♾️ shell 代码:docker build -f dockerfile -t jiu/centos .
#我这是在创建的文件里面,所以没有写绝对路径,注意!
[root@iZj6c5ctiawsbu90vbskdwZ jiusheng]# docker build -f dockerfile -t jiu/centos .
Sending build context to Docker daemon 2.048kB
Step 1/4 : FROM centos
latest: Pulling from library/centos
7a0437f04f83: Pull complete
Digest: sha256:5528e8b1b1719d34604c87e11dcd1c0a20bedf46e83b5632cdeac91b8c04efc1
Status: Downloaded newer image for centos:latest
---> 300e315adb2f
Step 2/4 : VOLUME ["jiusheng01","jiusheng02"]
---> Running in 493198964ebc
Removing intermediate container 493198964ebc
---> 708ee122fc35
Step 3/4 : CMD echo "-------jiushengzuishuai------"
---> Running in 4fa544e52a5d
Removing intermediate container 4fa544e52a5d
---> 1636e3ed06f7
Step 4/4 : CMD /bin/bash
---> Running in 8e41d980a363
Removing intermediate container 8e41d980a363
---> e812a670c034
Successfully built e812a670c034
Successfully tagged jiu/centos:latest
#我这里没有centos,所以多了一个下载
查看是否构建成功
♾️ shell 代码:docker images
[root@iZj6c5ctiawsbu90vbskdwZ jiusheng]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
jiu/centos latest e812a670c034 30 seconds ago 209MB
nginx latest 08b152afcfae 6 days ago 133MB
mysql 5.7 8cf625070931 6 days ago 448MB
centos latest 300e315adb2f 7 months ago 209MB
运行镜像
♾️ shell 代码:docker run -it e812a670c034 /bin/bash
[root@85a2c18ffc33 /]# ls -l
total 56
lrwxrwxrwx 1 root root 7 Nov 3 2020 bin -> usr/bin
drwxr-xr-x 5 root root 360 Jul 29 07:22 dev
drwxr-xr-x 1 root root 4096 Jul 29 07:22 etc
drwxr-xr-x 2 root root 4096 Nov 3 2020 home
drwxr-xr-x 2 root root 4096 Jul 29 07:22 jiusheng01
drwxr-xr-x 2 root root 4096 Jul 29 07:22 jiusheng02
lrwxrwxrwx 1 root root 7 Nov 3 2020 lib -> usr/lib
lrwxrwxrwx 1 root root 9 Nov 3 2020 lib64 -> usr/lib64
drwx------ 2 root root 4096 Dec 4 2020 lost+found
drwxr-xr-x 2 root root 4096 Nov 3 2020 media
drwxr-xr-x 2 root root 4096 Nov 3 2020 mnt
drwxr-xr-x 2 root root 4096 Nov 3 2020 opt
dr-xr-xr-x 102 root root 0 Jul 29 07:22 proc
dr-xr-x--- 2 root root 4096 Dec 4 2020 root
drwxr-xr-x 11 root root 4096 Dec 4 2020 run
lrwxrwxrwx 1 root root 8 Nov 3 2020 sbin -> usr/sbin
drwxr-xr-x 2 root root 4096 Nov 3 2020 srv
dr-xr-xr-x 13 root root 0 Jul 29 01:08 sys
drwxrwxrwt 7 root root 4096 Dec 4 2020 tmp
drwxr-xr-x 12 root root 4096 Dec 4 2020 usr
drwxr-xr-x 20 root root 4096 Dec 4 2020 var
查看挂载地址
♾️ shell 代码:docker inspect 85a2c18ffc33
"Mounts": [
{
"Type": "volume",
"Name": "d6f8d3df6d8bf7a8067a547550ecf24ec6d8e2217a6f66ec4b694175eca015e9",
"Source": "/var/lib/docker/volumes/d6f8d3df6d8bf7a8067a547550ecf24ec6d8e2217a6f66ec4b694175eca015e9/_data",
"Destination": "jiusheng02",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
},
{
"Type": "volume",
"Name": "29cbc761ed2c5cfad7360e0b30918f29011d2a6b4962f50a245501b25323380b",
"Source": "/var/lib/docker/volumes/29cbc761ed2c5cfad7360e0b30918f29011d2a6b4962f50a245501b25323380b/_data",
"Destination": "jiusheng01",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
}
],
#我们可以看到也是挂载到了对于的目录下,后面的操作就不在演示了
数据卷容器
定义:命名的容器挂载数据卷,其它容器通过挂载这个(父容器)实现数据共享,挂载数据卷的容器,称之为数据卷容器
容器间的传递共享
♾️ shell 代码:docker run -it --name 子容器名 --volumes-from 父容器名 镜像名
- 启动一个子容器
docker run -it --name jiu01 --volumes-from 85a2c18ffc33 e812a670c034
#这里直接使用上面创建的容器为父容器,估不再新建,直接创建子容器
- 在子容器里面创建一个文件
[root@3f816b8ff216 /]# cd jiusheng01
[root@3f816b8ff216 jiusheng01]# touch jiushengya.txt
- 到父容器里面查看
[root@85a2c18ffc33 /]# cd jiusheng01
[root@85a2c18ffc33 jiusheng01]# ls
jiushengya.txt
#数据同步共享
所有子容器数据与父容器以及父容器的其它子容器同步,同时删除容器不会删除数据,父容器停止或者删除,不会影响子容器
DocKerFile
dockerfile概念
dockerfile 是用来构建docker镜像文件的,一个命令参数脚本!
构建步骤
- 编写一个dockerfile文件
- 使用doicker build 构建一个镜像
- 使用docker run 运行镜像
- 使用docker push 发布一个镜像
Dockerfile优点
- 易于版本化管理,Dockerfile 本身是一个文本文件,方便存放在代码仓库做版本管理,可以很方便地找到各个版本之间的变更历史
- 过程可追溯,Dockerfile 的每一行指令代表一个镜像层,根据 Dockerfile 的内容即可很明确地查看镜像的完整构建过程
- 屏蔽构建环境异构,使用 Dockerfile 构建镜像无须考虑构建环境,基于相同 Dockerfile 无论在哪里运行,构建结果都一致
Dockerfile构建过程解析
基础
- 每条指令都必须大写字母,后面跟随至少一个参数
- 指令从上到下按序执行
表示注释
- 每条指令都会创建一个镜像层,并对镜像进行提交
Dockerfile 书写原则
- 单一原则
- 由于容器的本质是进程,一个容器代表一个进程,因此不同功能的应用应该尽量拆分为不同的容器,每个容器只负责单一业务进程。
- 注释信息
- Dockerfile 也是一种代码,我们应该保持良好的代码编写习惯,晦涩难懂的代码尽量添加注释,让协作者可以一目了然地知道每一行代码的作用,并且方便扩展和使用。
- 保持容器最小化
- 应该避免安装无用的软件包,比如在一个 nginx 镜像中,我并不需要安装 vim 、gcc 等开发编译工具。这样不仅可以加快容器构建速度,而且可以避免镜像体积过大。
- 合理选择基础镜像
- 容器的核心是应用,因此只要基础镜像能够满足应用的运行环境即可。例如一个Java类型的应用运行时只需要JRE,并不需要JDK,因此我们的基础镜像只需要安装JRE环境即可。
- 使用 .dockerignore 文件
- 在使用git时,我们可以使用.gitignore文件忽略一些不需要做版本管理的文件。同理,使用.dockerignore文件允许我们在构建时,忽略一些不需要参与构建的文件,从而提升构建效率。.dockerignore的定义类似于.gitignore。
- 尽量使用构建缓存
Docker 构建过程中,每一条 Dockerfile 指令都会提交为一个镜像层,下一条指令都是基于上一条指令构建的。如果构建时发现要构建的镜像层的父镜像层已经存在,并且下一条命令使用了相同的指令,即可命中构建缓存。
Docker 构建时判断是否需要使用缓存的规则如下:
- 从当前构建层开始,比较所有的子镜像,检查所有的构建指令是否与当前完全一致,如果不一致,则不使用缓存;
- 一般情况下,只需要比较构建指令即可判断是否需要使用缓存,但是有些指令除外(例如ADD和COPY)。
- 对于ADD和COPY指令不仅要校验命令是否一致,还要为即将拷贝到容器的文件计算校验和(根据文件内容计算出的一个数值,如果两个文件计算的数值一致,表示两个文件内容一致 ),命令和校验和完全一致,才认为命中缓存。
- 因此,基于 Docker 构建时的缓存特性,我们可以把不轻易改变的指令放到 Dockerfile 前面(例如安装软件包),而可能经常发生改变的指令放在 Dockerfile 末尾(例如编译应用程序)。
- 正确设置时区
我们从 Docker Hub 拉取的官方操作系统镜像大多数都是 UTC 时间(世界标准时间)。如果你想要在容器中使用中国区标准时间(东八区),请根据使用的操作系统修改相应的时区信息
♾️ shell 代码:#Dockerfile 几种常用操作系统的修改方式: #Ubuntu 和Debian 系统 RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime RUN echo "Asia/Shanghai" >> /etc/timezone #CentOS系统 RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
- 使用国内软件源加快镜像构建速度
- 由于我们常用的官方操作系统镜像基本都是国外的,软件服务器大部分也在国外,所以我们构建镜像的时候想要安装一些软件包可能会非常慢。
- 最小化镜像层数
- 在构建镜像时尽可能地减少 Dockerfile 指令行数。例如我们要在 CentOS 系统中安装make和net-tools两个软件包,应该在 Dockerfile 中使用以下指令:
- ♾️ shell 代码:
RUN yum install -y make net-tools
- 而不应该写成这样:
- ♾️ shell 代码:
RUN yum install -y make RUN yum install -y net-tools
dockerfile指令
所有的关键字都必须是大写,同时第一行不能是注释,必须是FROM
表示注释
1.FROM : 基础镜像
2.MANTAINER:镜像维护作者名和邮箱
3.RUN:容器构建需要的命令
4.EXPOSE:暴露端口
5.WORKDIR:登录后默认的工作目录
6.ENV:构建镜像过程中设置的环境变量
7.ADD:将宿主机目录下的文件拷贝进镜像并且会自动处理url和解压tar压缩包
8.COPY:将从构建上下文目录中(源路径)的文件/目录复制到新的一层的镜像内的(目标路径)位置
9.VOLUME:容器数据卷
10.CMD:指定容器启动时需要运行的命令,dockerFile中可以有多个cmd指令,但只有最后一个生效,cmd会被docker run之后的参数替换
11.ENTRYPOINT:指定一个容器启动时要运行的命令,可以有多条,都会生效
12.ONBUILD:当构建一个被继承的dockerFile时的运行命令,父镜像在被子镜像继承后,父镜像的onbuild被触发
实战测试
官方配置
Docker Hub 中 99% 镜像都是从这个基础镜像过来的 FROM scratch,然后配置需要的软件和配置来进行构建的♾️ shell 代码:
FROM scratch 指定镜像
ADD centos-7-x86_64-docker.tar.xz / #cenos7压缩包
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"]
创建一个自己的镜像♾️ shell 代码:
#进入home目录
cd home/
#创建DocKerFile文件
mkdir DocKerFile
#进入dockerfile
cd DocKerFile/
#随便创建一个文件名,写脚本
vim mycenos
#写入如下信息
FROM centos
#指定镜像
MAINTAINER jiusheng<2936688581@qq.com> #作者信息
ENV MYPATH /usr/local #工作目录
WORKDIR $MYPATH
RUN yum -y install vim net-tools #下载vim 和net-tools
EXPOSE 80 #暴露端口
CMD echo $MYPATH
CMD echo "-----jiusheng--" #输出信息
CMD /bin/bash
运行命令,构建镜像
♾️ shell 代码:基本格式:
注意,后面是有一个 .
docker build -f 文件路径 -t 镜像名:[tag] .
[root@iZj6c5ctiawsbu90vbskdwZ DocKerFile]# docker build -f mycenos -t jiu_centos .
Sending build context to Docker daemon 2.048kB
Step 1/9 : FROM centos
---> 300e315adb2f
Step 2/9 : MAINTAINER jiusheng<2936688581@qq.com>
---> Running in 591cbf9c38f9
Removing intermediate container 591cbf9c38f9
---> cbdb558b172f
Step 3/9 : ENV MYPATH /usr/local
---> Running in f9c692dbac96
Removing intermediate container f9c692dbac96
---> 51316b596261
Step 4/9 : WORKDIR $MYPATH
---> Running in 3d4f6d2f173d
Removing intermediate container 3d4f6d2f173d
---> 51338bb008c2
Step 5/9 : RUN yum -y install vim net-tools
---> Running in cf3421730130
CentOS Linux 8 - AppStream 6.8 MB/s | 8.3 MB 00:01
CentOS Linux 8 - BaseOS 4.9 MB/s | 4.5 MB 00:00
CentOS Linux 8 - Extras 22 kB/s | 9.8 kB 00:00
Dependencies resolved.
================================================================================
Package Arch Version Repository Size
================================================================================
Installing:
net-tools x86_64 2.0-0.52.20160912git.el8 baseos 322 k
vim-enhanced x86_64 2:8.0.1763-15.el8 appstream 1.4 M
Installing dependencies:
gpm-libs x86_64 1.20.7-17.el8 appstream 39 k
vim-common x86_64 2:8.0.1763-15.el8 appstream 6.3 M
vim-filesystem noarch 2:8.0.1763-15.el8 appstream 48 k
which x86_64 2.21-12.el8 baseos 49 k
Transaction Summary
================================================================================
Install 6 Packages
Total download size: 8.1 M
Installed size: 31 M
Downloading Packages:
(1/6): gpm-libs-1.20.7-17.el8.x86_64.rpm 395 kB/s | 39 kB 00:00
(2/6): vim-enhanced-8.0.1763-15.el8.x86_64.rpm 13 MB/s | 1.4 MB 00:00
(3/6): vim-filesystem-8.0.1763-15.el8.noarch.rp 909 kB/s | 48 kB 00:00
(4/6): which-2.21-12.el8.x86_64.rpm 2.3 MB/s | 49 kB 00:00
(5/6): vim-common-8.0.1763-15.el8.x86_64.rpm 30 MB/s | 6.3 MB 00:00
(6/6): net-tools-2.0-0.52.20160912git.el8.x86_6 2.9 MB/s | 322 kB 00:00
--------------------------------------------------------------------------------
Total 7.4 MB/s | 8.1 MB 00:01
warning: /var/cache/dnf/appstream-02e86d1c976ab532/packages/gpm-libs-1.20.7-17.el8.x86_64.rpm: Header V3 RSA/SHA256 Signature, key ID 8483c65d: NOKEY
CentOS Linux 8 - AppStream 1.4 MB/s | 1.6 kB 00:00
Importing GPG key 0x8483C65D:
Userid : "CentOS (CentOS Official Signing Key) <security@centos.org>"
Fingerprint: 99DB 70FA E1D7 CE22 7FB6 4882 05B5 55B3 8483 C65D
From : /etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial
Key imported successfully
Running transaction check
Transaction check succeeded.
Running transaction test
Transaction test succeeded.
Running transaction
Preparing : 1/1
Installing : which-2.21-12.el8.x86_64 1/6
Installing : vim-filesystem-2:8.0.1763-15.el8.noarch 2/6
Installing : vim-common-2:8.0.1763-15.el8.x86_64 3/6
Installing : gpm-libs-1.20.7-17.el8.x86_64 4/6
Running scriptlet: gpm-libs-1.20.7-17.el8.x86_64 4/6
Installing : vim-enhanced-2:8.0.1763-15.el8.x86_64 5/6
Installing : net-tools-2.0-0.52.20160912git.el8.x86_64 6/6
Running scriptlet: net-tools-2.0-0.52.20160912git.el8.x86_64 6/6
Running scriptlet: vim-common-2:8.0.1763-15.el8.x86_64 6/6
Verifying : gpm-libs-1.20.7-17.el8.x86_64 1/6
Verifying : vim-common-2:8.0.1763-15.el8.x86_64 2/6
Verifying : vim-enhanced-2:8.0.1763-15.el8.x86_64 3/6
Verifying : vim-filesystem-2:8.0.1763-15.el8.noarch 4/6
Verifying : net-tools-2.0-0.52.20160912git.el8.x86_64 5/6
Verifying : which-2.21-12.el8.x86_64 6/6
Installed:
gpm-libs-1.20.7-17.el8.x86_64
net-tools-2.0-0.52.20160912git.el8.x86_64
vim-common-2:8.0.1763-15.el8.x86_64
vim-enhanced-2:8.0.1763-15.el8.x86_64
vim-filesystem-2:8.0.1763-15.el8.noarch
which-2.21-12.el8.x86_64
Complete!
Removing intermediate container cf3421730130
---> 96c4435f5f36
Step 6/9 : EXPOSE 80
---> Running in a5363e9470cd
Removing intermediate container a5363e9470cd
---> ee1bd76b09e4
Step 7/9 : CMD echo $MYPATH
---> Running in 110b43851555
Removing intermediate container 110b43851555
---> bcb634848307
Step 8/9 : CMD echo "-----jiusheng--"
---> Running in e8acecac7db8
Removing intermediate container e8acecac7db8
---> 700270977443
Step 9/9 : CMD /bin/bash
---> Running in 5df30afb5f3f
Removing intermediate container 5df30afb5f3f
---> aeeaf736a24e
Successfully built aeeaf736a24e
Successfully tagged jiu_centos:latest
查看是否构建成功
♾️ shell 代码:[root@iZj6c5ctiawsbu90vbskdwZ DocKerFile]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
jiu_centos latest aeeaf736a24e 13 minutes ago 275MB
nginx latest 08b152afcfae 9 days ago 133MB
mysql 5.7 8cf625070931 9 days ago 448MB
centos latest 300e315adb2f 7 months ago 209MB
测试运行
♾️ shell 代码:docker run -it jiu_centos
[root@iZj6c5ctiawsbu90vbskdwZ DocKerFile]# docker run -it jiu_centos
#查看工作目录
[root@c2538f1711ea local]# pwd
/usr/local
#是我们设定的工作目录
#检测功能是否能用
[root@c2538f1711ea local]# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.17.0.2 netmask 255.255.0.0 broadcast 172.17.255.255
ether 02:42:ac:11:00:02 txqueuelen 0 (Ethernet)
RX packets 8 bytes 656 (656.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
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
loop txqueuelen 1000 (Local Loopback)
RX packets 0 bytes 0 (0.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
[root@c2538f1711ea local]# vim jiu
[1]+ Stopped vim jiu
#完全能用,构建成功
列出本地镜像的变更历史
♾️ shell 代码:docker history 镜像名
[root@iZj6c5ctiawsbu90vbskdwZ DocKerFile]# docker history jiu_centos
IMAGE CREATED CREATED BY SIZE COMMENT
aeeaf736a24e 26 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "/bin… 0B
700270977443 26 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "echo… 0B
bcb634848307 26 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "echo… 0B
ee1bd76b09e4 26 minutes ago /bin/sh -c #(nop) EXPOSE 80 0B
96c4435f5f36 26 minutes ago /bin/sh -c yum -y install vim net-tools 66MB
51338bb008c2 27 minutes ago /bin/sh -c #(nop) WORKDIR /usr/local 0B
51316b596261 27 minutes ago /bin/sh -c #(nop) ENV MYPATH=/usr/local 0B
cbdb558b172f 27 minutes ago /bin/sh -c #(nop) MAINTAINER jiusheng<29366… 0B
300e315adb2f 7 months ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0B
<missing> 7 months ago /bin/sh -c #(nop) LABEL org.label-schema.sc… 0B
<missing> 7 months ago /bin/sh -c #(nop) ADD file:bd7a2aed6ede423b7… 209MB
CMD 和 ENTRYPOINT 区别
测试CMD
♾️ shell 代码:# 编写dockerfile文件
[root@iZj6c5ctiawsbu90vbskdwZ DocKerFile]# vim ceshi
FROM centos
CMD ["ls","-a"]
# 构建镜像
[root@iZj6c5ctiawsbu90vbskdwZ DocKerFile]# docker build -f ceshi -t ceshiya .
Sending build context to Docker daemon 3.072kB
Step 1/2 : FROM centos
---> 300e315adb2f
Step 2/2 : CMD ["ls","-a"]
---> Running in f4f284cd463d
Removing intermediate container f4f284cd463d
---> c9afee7729d7
Successfully built c9afee7729d7
Successfully tagged ceshiya:latest
# run 运行 发现我们的 ls -a 命令生效
[root@iZj6c5ctiawsbu90vbskdwZ DocKerFile]# docker run ceshiya
.
..
.dockerenv
bin
dev
etc
home
lib
lib64
lost+found
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
var
# 想追加一个命令 -l ls -al
[root@iZj6c5ctiawsbu90vbskdwZ DocKerFile]# docker run ceshiya -l
docker: Error response from daemon: OCI runtime create failed: container_linux.go:370: starting container process caused: exec: "-l": executable file not found in $PATH: unknown.
# cmd 的情况下 -l 替换了 CMD ["ls","-a"] 命令 -l 不是命令 所以报错
测试ENTRYPOINT
♾️ shell 代码:# 编写dockerfile文件
[root@root dockerfile]# vi ceshi01
FROM centos
ENTRYPOINT ["ls","-a"]
# 构建镜像
[root@iZj6c5ctiawsbu90vbskdwZ DocKerFile]# docker build -f ceshi01 -t ceshiya01 .
Sending build context to Docker daemon 4.096kB
Step 1/2 : FROM centos
---> 300e315adb2f
Step 2/2 : ENTRYPOINT ["ls","-a"]
---> Running in 5490b3031487
Removing intermediate container 5490b3031487
---> 6102c6aeb29c
Successfully built 6102c6aeb29c
Successfully tagged ceshiya01:latest
# run 运行 发现我们的 ls -a 命令生效
[root@iZj6c5ctiawsbu90vbskdwZ DocKerFile]# docker run ceshiya01
.
..
.dockerenv
bin
dev
etc
home
lib
lib64
lost+found
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
var
# 想追加一个命令 -l ls -al 发现生效
[root@iZj6c5ctiawsbu90vbskdwZ DocKerFile]# docker run ceshiya01 -l
total 56
drwxr-xr-x 1 root root 4096 Aug 1 03:02 .
drwxr-xr-x 1 root root 4096 Aug 1 03:02 ..
-rwxr-xr-x 1 root root 0 Aug 1 03:02 .dockerenv
lrwxrwxrwx 1 root root 7 Nov 3 2020 bin -> usr/bin
drwxr-xr-x 5 root root 340 Aug 1 03:02 dev
drwxr-xr-x 1 root root 4096 Aug 1 03:02 etc
drwxr-xr-x 2 root root 4096 Nov 3 2020 home
lrwxrwxrwx 1 root root 7 Nov 3 2020 lib -> usr/lib
lrwxrwxrwx 1 root root 9 Nov 3 2020 lib64 -> usr/lib64
drwx------ 2 root root 4096 Dec 4 2020 lost+found
drwxr-xr-x 2 root root 4096 Nov 3 2020 media
drwxr-xr-x 2 root root 4096 Nov 3 2020 mnt
drwxr-xr-x 2 root root 4096 Nov 3 2020 opt
dr-xr-xr-x 109 root root 0 Aug 1 03:02 proc
dr-xr-x--- 2 root root 4096 Dec 4 2020 root
drwxr-xr-x 11 root root 4096 Dec 4 2020 run
lrwxrwxrwx 1 root root 8 Nov 3 2020 sbin -> usr/sbin
drwxr-xr-x 2 root root 4096 Nov 3 2020 srv
dr-xr-xr-x 13 root root 0 Jul 29 01:08 sys
drwxrwxrwt 7 root root 4096 Dec 4 2020 tmp
drwxr-xr-x 12 root root 4096 Dec 4 2020 usr
drwxr-xr-x 20 root root 4096 Dec 4 2020 var
发布镜像
发布到官方 docker hub 上
需要注册账号!
查看登录命令
♾️ shell 代码:[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker login --help
Usage: docker login [OPTIONS] [SERVER]
Log in to a Docker registry.
If no server is specified, the default is defined by the daemon.
Options:
-p, --password string Password
--password-stdin Take the password from stdin
-u, --username string Username
[root@iZj6c5ctiawsbu90vbskdwZ ~]#
登录账号
♾️ shell 代码:[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker login -u jiusheng
Password:
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
#这样就算成功了
Login Succeeded
[root@iZj6c5ctiawsbu90vbskdwZ ~]#
提交镜像
♾️ shell 代码:docker push 信息/镜像:版本号
docker push jiusheng/centos:1.0
发布到阿里云
- 登录阿里云
- 找到容器镜像服务
- 点击个人实例
- 点击创建镜像仓库
- 点击本地仓库创建
- 查看阿里云帮助文档
docker网络
初识docker0
- 这是我们没有安装docker时候的网络
[root@iZj6c5ctiawsbu90vbskdwZ ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 00:16:3e:01:9e:7a brd ff:ff:ff:ff:ff:ff
inet 172.21.27.152/18 brd 172.21.63.255 scope global dynamic eth0
valid_lft 315359962sec preferred_lft 315359962sec
- 我们安装好docker之后会发现多了一个docker0
[root@iZj6c5ctiawsbu90vbskdwZ ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 00:16:3e:01:9e:7a brd ff:ff:ff:ff:ff:ff
inet 172.21.27.152/18 brd 172.21.63.255 scope global dynamic eth0
valid_lft 315359848sec preferred_lft 315359848sec
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 02:42:4c:03:0f:26 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
- 安装Docker时,它会自动创建三个网络,bridge(创建容器默认连接到此网络)、 none 、host
- docker network 指令了解
[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker network --help
Usage: docker network COMMAND
Manage networks
Commands:
connect Connect a container to a network # 将容器连接到网络
create Create a network #创建网络
disconnect Disconnect a container from a network # 断开容器与网络的连接
inspect Display detailed information on one or more networks # 显示一个或多个网络的详细信息
ls List networks #列出所有网络
prune Remove all unused networks #删除所有未使用的网络
rm Remove one or more networks #删除一个或者多个网络
Run 'docker network COMMAND --help' for more information on a command.
- 验证一下docker0默认网络
#启动一个容器
[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker run -d -P --name tomcat01 tomcat
Unable to find image 'tomcat:latest' locally
latest: Pulling from library/tomcat
627b765e08d1: Pull complete
c040670e5e55: Pull complete
073a180f4992: Pull complete
bf76209566d0: Pull complete
f10db7ba7580: Pull complete
5b2f970878fa: Pull complete
ed434bfebf18: Pull complete
f6c437110aa9: Pull complete
a772951f83db: Pull complete
752225c3768e: Pull complete
Digest: sha256:6e40250d8fac4eca05c2067cb81f79427e4ddbaf4e78d5ecd21c35e8c5f2bfcf
Status: Downloaded newer image for tomcat:latest
6017ba277147c0b023ee2aa475108a4f8b88e8f7d182180308fc60ff0f41c714
#查看网络
[root@iZj6c5ctiawsbu90vbskdwZ ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 00:16:3e:01:9e:7a brd ff:ff:ff:ff:ff:ff
inet 172.21.27.152/18 brd 172.21.63.255 scope global dynamic eth0
valid_lft 315358148sec preferred_lft 315358148sec
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:4c:03:0f:26 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
7: veth961d52c@if6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
link/ether b2:82:8d:b4:75:6b brd ff:ff:ff:ff:ff:ff link-netnsid 0
#查看容器里面的网络
root@6017ba277147:/usr/local/tomcat# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
6: eth0@if7: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
#我们可以看到容器内有一个eth0@if7的网络,同时可以发现eth0@if7和veth961d52c@if6是相互绑定的,也是成对出现的。
#查看能否ping通容器
[root@iZj6c5ctiawsbu90vbskdwZ ~]# ping 172.17.0.2
PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.095 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.078 ms
64 bytes from 172.17.0.2: icmp_seq=3 ttl=64 time=0.041 ms
#发现可以ping通
原理
我们每启动一个容器,docker就会给我们的容器分配一个ip,docker使用的是桥接模式,使用的技术evth-pair技术
同时ip是成对出现的
evth-pair起到一个连接的桥梁,一般用来连接虚拟网络设备
- 在启动一个容器
#查看网卡
[root@iZj6c5ctiawsbu90vbskdwZ ~]# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 00:16:3e:01:9e:7a brd ff:ff:ff:ff:ff:ff
inet 172.21.27.152/18 brd 172.21.63.255 scope global dynamic eth0
valid_lft 315357189sec preferred_lft 315357189sec
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:4c:03:0f:26 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
7: veth961d52c@if6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
link/ether b2:82:8d:b4:75:6b brd ff:ff:ff:ff:ff:ff link-netnsid 0
9: veth3880b7f@if8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
link/ether b6:23:87:6f:bc:ef brd ff:ff:ff:ff:ff:ff link-netnsid 1
#可以看到有多了一对
- 容器ping容器
[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker exec -it tomcat02 ping 172.17.0.2
PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.082 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.055 ms
64 bytes from 172.17.0.2: icmp_seq=3 ttl=64 time=0.050 ms
#我们可以看到,是可以相互ping通的
网络图
--link
不推荐使用,只做了解
不通过ip来访问容器,直接通过容器名访问
- 容器和容器进行ping
[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker exec -it tomcat01 ping tomcat02
ping: tomcat02: Name or service not known
- 使用--link
[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker run -d -P --name tomcat03 --link tomcat02 tomcat
4438f44dd6ff78a67892c526fcd5cf7ca7f1177699f0a3d8e24217e42515c673
- 查看是否可以ping通
[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker exec -it tomcat03 ping tomcat02
PING tomcat02 (172.17.0.3) 56(84) bytes of data.
64 bytes from tomcat02 (172.17.0.3): icmp_seq=1 ttl=64 time=0.074 ms
64 bytes from tomcat02 (172.17.0.3): icmp_seq=2 ttl=64 time=0.055 ms
64 bytes from tomcat02 (172.17.0.3): icmp_seq=3 ttl=64 time=0.058 ms
#发现可以通过容器名ping通
- 反向是否可以ping通
[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker exec -it tomcat02 ping tomcat03
ping: tomcat03: Name or service not known
#发现是ping不同的,应为没有配置
- 查看网络信息
[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
f4e21fcb0d76 bridge bridge local
3c7452c40eb3 host host local
a122752ffd10 none null local
[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker network inspect f4e21fcb0d76
[
{
"Name": "bridge",
"Id": "f4e21fcb0d76f6a60dd870d02ed9604686240449350685f8100a9525fc564be1",
"Created": "2021-08-01T16:00:00.258764824+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "172.17.0.0/16" #docker0
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"21b9e1bdfe0988f74199afb82805e502cfda94fccc8e269728c98b54f26637de": {
"Name": "tomcat02",
"EndpointID": "bd4419e2ca78725ddae30f95adc0d523680ff16c95960971d8fbaa823b531f1d",
"MacAddress": "02:42:ac:11:00:03",
"IPv4Address": "172.17.0.3/16",
"IPv6Address": ""
},
"4438f44dd6ff78a67892c526fcd5cf7ca7f1177699f0a3d8e24217e42515c673": {
"Name": "tomcat03",
"EndpointID": "070b04e67e1dfbdeb5039b9db6d61e1ee0989953467b4edd9cc0641adbbab21f",
"MacAddress": "02:42:ac:11:00:04",
"IPv4Address": "172.17.0.4/16",
"IPv6Address": ""
},
"6017ba277147c0b023ee2aa475108a4f8b88e8f7d182180308fc60ff0f41c714": {
"Name": "tomcat01",
"EndpointID": "717371bbe0ff45dd69480cd95bc1bfb41c0a02b10fef0df3a11fe46b2bf6cbe6",
"MacAddress": "02:42:ac:11:00:02",
"IPv4Address": "172.17.0.2/16",
"IPv6Address": ""
}
},
"Options": {
"com.docker.network.bridge.default_bridge": "true",
"com.docker.network.bridge.enable_icc": "true",
"com.docker.network.bridge.enable_ip_masquerade": "true",
"com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
"com.docker.network.bridge.name": "docker0",
"com.docker.network.driver.mtu": "1500"
},
"Labels": {}
}
]
#查看tomcat03
[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker inspect 4438f44dd6ff
[
{
"Id": "4438f44dd6ff78a67892c526fcd5cf7ca7f1177699f0a3d8e24217e42515c673",
"Created": "2021-08-01T09:41:06.910147871Z",
"Path": "catalina.sh",
"Args": [
"run"
],
"State": {
"Status": "running",
"Running": true,
"Paused": false,
"Restarting": false,
"OOMKilled": false,
"Dead": false,
"Pid": 13874,
"ExitCode": 0,
"Error": "",
"StartedAt": "2021-08-01T09:41:07.368939358Z",
"FinishedAt": "0001-01-01T00:00:00Z"
},
"Image": "sha256:46cfbf1293b176161813fa05bb8f7e82df1ec7def5c226c48bc48a60ed305ac7",
"ResolvConfPath": "/var/lib/docker/containers/4438f44dd6ff78a67892c526fcd5cf7ca7f1177699f0a3d8e24217e42515c673/resolv.conf",
"HostnamePath": "/var/lib/docker/containers/4438f44dd6ff78a67892c526fcd5cf7ca7f1177699f0a3d8e24217e42515c673/hostname",
"HostsPath": "/var/lib/docker/containers/4438f44dd6ff78a67892c526fcd5cf7ca7f1177699f0a3d8e24217e42515c673/hosts",
"LogPath": "/var/lib/docker/containers/4438f44dd6ff78a67892c526fcd5cf7ca7f1177699f0a3d8e24217e42515c673/4438f44dd6ff78a67892c526fcd5cf7ca7f1177699f0a3d8e24217e42515c673-json.log",
"Name": "/tomcat03",
"RestartCount": 0,
"Driver": "overlay2",
"Platform": "linux",
"MountLabel": "",
"ProcessLabel": "",
"AppArmorProfile": "",
"ExecIDs": [
"e2d063fb5a968904b5e3ec6def704cc3790f9b1efcd9ce7c0240a939383ee549"
],
"HostConfig": {
"Binds": null,
"ContainerIDFile": "",
"LogConfig": {
"Type": "json-file",
"Config": {}
},
"NetworkMode": "default",
"PortBindings": {},
"RestartPolicy": {
"Name": "no",
"MaximumRetryCount": 0
},
"AutoRemove": false,
"VolumeDriver": "",
"VolumesFrom": null,
"CapAdd": null,
"CapDrop": null,
"CgroupnsMode": "host",
"Dns": [],
"DnsOptions": [],
"DnsSearch": [],
"ExtraHosts": null,
"GroupAdd": null,
"IpcMode": "private",
"Cgroup": "",
"Links": [
"/tomcat02:/tomcat03/tomcat02" #这里可以发现tomcat03里面的配置出现了tomcat02
],
"OomScoreAdj": 0,
"PidMode": "",
"Privileged": false,
"PublishAllPorts": true,
"ReadonlyRootfs": false,
"SecurityOpt": null,
"UTSMode": "",
"UsernsMode": "",
"ShmSize": 67108864,
"Runtime": "runc",
"ConsoleSize": [
0,
0
],
#进入Tomcat03查看
[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker exec -it tomcat03 cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.3 tomcat02 21b9e1bdfe09
172.17.0.4 4438f44dd6ff
#我们可以发现,这里直接就绑定了Tomcat02
自定义网络
容器互联
- 创建一个jiusheng网络
#删除之前的所有容器
docker rm -f $(docker ps -aq)
#创建网络
[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 jiusheng
db61398754c4de6d331db1788071e11ad9fa5883167cba1f0bf021bf671527c8
[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
f4e21fcb0d76 bridge bridge local
3c7452c40eb3 host host local
db61398754c4 jiusheng bridge local
a122752ffd10 none null local
- 查看创建网络信息
[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker network inspect db61398754c4
[
{
"Name": "jiusheng",
"Id": "db61398754c4de6d331db1788071e11ad9fa5883167cba1f0bf021bf671527c8",
"Created": "2021-08-01T17:58:35.111862913+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "192.168.0.0/16",
"Gateway": "192.168.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {},
"Options": {},
"Labels": {}
}
]
- 使用jiushneg网络
[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker run -d -P --name tomcat02 --net jiusheng tomcat
1a04efb744627d546dbb8e22ed162062c56718b24836a45ee28d5f33af83f994
[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker run -d -P --name tomcat01 --net jiusheng tomcat
ecccd3d1869c3d95d6e28787765bf26eea01866bf317b4ea3fe01f8549fea281
[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ecccd3d1869c tomcat "catalina.sh run" 4 seconds ago Up 3 seconds 0.0.0.0:49160->8080/tcp tomcat01
1a04efb74462 tomcat "catalina.sh run" 12 seconds ago Up 12 seconds 0.0.0.0:49159->8080/tcp tomcat02
- 容器互相ping
[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker exec -it tomcat01 ping tomcat02
PING tomcat02 (192.168.0.2) 56(84) bytes of data.
64 bytes from tomcat02.jiusheng (192.168.0.2): icmp_seq=1 ttl=64 time=0.061 ms
64 bytes from tomcat02.jiusheng (192.168.0.2): icmp_seq=2 ttl=64 time=0.051 ms
64 bytes from tomcat02.jiusheng (192.168.0.2): icmp_seq=3 ttl=64 time=0.063 ms
#发现可以直接ping通
自定义网络好处
- 不同集群的网络是相对的
- 让容器的网络基于dns的域名解析
- 拥有与宿主机之间安全的隔离环境
- 自由的选择或放弃一个网络
不同网络之间的连通
- 创建两个不通网络的容器
[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker run -d -P --name tomcat01 --net jiusheng tomcat
76ab3aba3e19257a29e6b4702a9145d7da4f59150e63de4af865cec4d8f94dfa
[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker run -d -P --name tomcat02 tomcat
8ad64e755f65f210eac46fd61c4ea2251810f4307b5d84e8aa67f764b30db50b
- 查看是否运行
[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8ad64e755f65 tomcat "catalina.sh run" 6 seconds ago Up 5 seconds 0.0.0.0:49162->8080/tcp tomcat02
76ab3aba3e19 tomcat "catalina.sh run" 16 seconds ago Up 15 seconds 0.0.0.0:49161->8080/tcp tomcat01
- 把tomcat加入jiusheng网络
[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker network connect jiusheng tomcat02
- 查看jiusheng网络
[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker network inspect jiusheng
[
{
"Name": "jiusheng",
"Id": "db61398754c4de6d331db1788071e11ad9fa5883167cba1f0bf021bf671527c8",
"Created": "2021-08-01T17:58:35.111862913+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "192.168.0.0/16",
"Gateway": "192.168.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"76ab3aba3e19257a29e6b4702a9145d7da4f59150e63de4af865cec4d8f94dfa": {
"Name": "tomcat01",
"EndpointID": "dd654b8cb571b23e2fa206b08097bf35ea4ea901b420b8cfd2309bda48f18b06",
"MacAddress": "02:42:c0:a8:00:02",
"IPv4Address": "192.168.0.2/16",
"IPv6Address": ""
},
#我们可以看到,这里直接就把tomcat02加入了进来
"8ad64e755f65f210eac46fd61c4ea2251810f4307b5d84e8aa67f764b30db50b": {
"Name": "tomcat02",
"EndpointID": "65c3a8b0634c77c689b512b5b9ee0a8473776cb63a8d45c44451f6bd41b8690f",
"MacAddress": "02:42:c0:a8:00:03",
"IPv4Address": "192.168.0.3/16",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {}
}
]
- 测试ping通
[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker exec -it tomcat01 ping tomcat02
PING tomcat02 (192.168.0.3) 56(84) bytes of data.
64 bytes from tomcat02.jiusheng (192.168.0.3): icmp_seq=1 ttl=64 time=0.088 ms
64 bytes from tomcat02.jiusheng (192.168.0.3): icmp_seq=2 ttl=64 time=0.061 ms
64 bytes from tomcat02.jiusheng (192.168.0.3): icmp_seq=3 ttl=64 time=0.048 ms
#发现是可以ping通的
- 反向ping
[root@iZj6c5ctiawsbu90vbskdwZ ~]# docker exec -it tomcat02 ping tomcat01
PING tomcat01 (192.168.0.2) 56(84) bytes of data.
64 bytes from tomcat01.jiusheng (192.168.0.2): icmp_seq=1 ttl=64 time=0.034 ms
64 bytes from tomcat01.jiusheng (192.168.0.2): icmp_seq=2 ttl=64 time=0.052 ms
64 bytes from tomcat01.jiusheng (192.168.0.2): icmp_seq=3 ttl=64 time=0.050 ms
#也是可以ping通的
部署redis,就不在演示了,也简单,自行百度
docker私有仓库
简介
在 Docker
中,当我们执行 docker pull xxx
的时候 ,它实际上是从 registry.hub.docker.com
这个地址去查找,这就是Docker
公司为我们提供的公共仓库。在工作中,我们不可能把企业项目push到公有仓库进行管理。所以为了更好的管理镜像,Docker
不仅提供了一个中央仓库,同时也允许我们搭建本地私有仓库。
官方私有仓库——registry
Docker 官方提供了一个搭建私有仓库的镜像 registry ,只需把镜像下载下来,运行容器并暴露5000端口,就可以使用了。
- 下载官方registry
docker pull registry
#这里默认下载最新版本
- 运行下载好的镜像
#查看镜像
docker images
#运行镜像
docker run -d -v /opt/registry:/var/lib/registry -p 5000:5000 --name ck registry
#Registry服务默认会将上传的镜像保存在容器的/var/lib/registry,我们将主机的/opt/registry目录挂载到该目录,即可实现将镜像保存到主机的/opt/registry目录了。
- 查看是否成功运行
docker ps
#访问网页ip:5000/v2
#出现{}及成功运行
- 验证服务
#通过push镜像来验证registry是否成功启动
#下载一个镜像
docker pull nginx
#查看镜像
docker images
#通过docker tag将该镜像标志为要推送到私有仓库
docker tag nginx:latest localhost:5000/nginx:latest
#通过 docker push 命令将 nginx 镜像 push到私有仓库中
docker push localhost:5000/nginx:latest
#访问ip:5000/v2/_catalog 查看私有仓库目录,可以看到刚上传的镜像
#下载私有仓库的镜像,使用如下命令
docker pull localhost:5000/镜像名:版本号
#例如
docker pull localhost:5000/nginx:latest
harbor私有仓库
docker 官方提供的私有仓库 registry,用起来虽然简单 ,但在管理的功能上存在不足。 Harbor是一个用于存储和分发Docker镜像的企业级Registry服务器,harbor使用的是官方的docker registry(v2命名是distribution)服务去完成。harbor在docker distribution的基础上增加了一些安全、访问控制、管理的功能以满足企业对于镜像仓库的需求。
harbor仓库使用到docker-compose,所以,你需要提前安装它。
- 安装
#选择一个文件下载
wget wget https://github.com/goharbor/harbor/releases/download/v2.5.0-rc1/harbor-offline-installer-v2.5.0-rc1.tgz -O harbor.tgz
#解压
tar zxvf harbor.tgz
#里面文件构建如下
-rw-r--r-- 1 root root 3361 Mar 4 16:37 common.sh
-rw-r--r-- 1 root root 657621862 Mar 4 16:37 harbor.v2.5.0.tar.gz
-rw-r--r-- 1 root root 9917 Mar 4 16:37 harbor.yml.tmpl
-rwxr-xr-x 1 root root 2500 Mar 4 16:37 install.sh
-rw-r--r-- 1 root root 11347 Mar 4 16:37 LICENSE
-rwxr-xr-x 1 root root 1881 Mar 4 16:37 prepare
#这里我们要修改一下harbor.yml.tmpl为harbor.yml
mv harbor.yml.tmpl ./ harbor.yml
#编辑配置文件harbor.yml
vim harbor.yml
#修改和注释一下内容
# Configuration file of Harbor
# The IP address or hostname to access admin UI and registry service.
# DO NOT use localhost or 127.0.0.1, because Harbor needs to be accessed by external clients.
hostname: 121.5.38.73 #这里就是说不能是localhost or 127.0.0.1,可以域名或者本机ip。
# http related config
http:
# port for http, default is 80. If https enabled, this port will redirect to https port
port: 80
# https related config
#https: #没有配置ssl证书,所以我们需要注释掉https的参数!
# https port for harbor, default is 443
# port: 443
# The path of cert and key files for nginx
# certificate: /your/certificate/path #ssl证书路径
# private_key: /your/private/key/path #ssl秘钥路径
#运行脚本install.sh部署仓库
./install.sh
#查看是否成功运行
[root@master harbor]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f384fc223903 goharbor/nginx-photon:v2.5.0 "nginx -g 'daemon of…" 4 hours ago Up 4 hours (healthy) 0.0.0.0:80->8080/tcp nginx
2fc54466355e goharbor/harbor-jobservice:v2.5.0 "/harbor/entrypoint.…" 4 hours ago Up 4 hours (healthy) harbor-jobservice
fd60b7ebe6b6 goharbor/harbor-core:v2.5.0 "/harbor/entrypoint.…" 4 hours ago Up 4 hours (healthy) harbor-core
970df803c63a goharbor/redis-photon:v2.5.0 "redis-server /etc/r…" 4 hours ago Up 4 hours (healthy) redis
c9b89fd1eb00 goharbor/harbor-db:v2.5.0 "/docker-entrypoint.…" 4 hours ago Up 4 hours (healthy) harbor-db
baf0553cafd7 goharbor/harbor-portal:v2.5.0 "nginx -g 'daemon of…" 4 hours ago Up 4 hours (healthy) harbor-portal
731b55a6a8e3 goharbor/registry-photon:v2.5.0 "/home/harbor/entryp…" 4 hours ago Up 4 hours (healthy) registry
06c3cad49a33 goharbor/harbor-registryctl:v2.5.0 "/home/harbor/start.…" 4 hours ago Up 4 hours (healthy) registryctl
c8980d2fb387 goharbor/harbor-log:v2.5.0 "/bin/sh -c /usr/loc…" 4 hours ago Up 4 hours (healthy) 127.0.0.1:1514->10514/tcp harbor-log
#查看运行后的镜像列表
[root@master harbor]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
registry latest 8948869ebfee 7 days ago 24.2MB
goharbor/harbor-exporter v2.5.0 70893e0bcdd3 11 days ago 90MB
goharbor/chartmuseum-photon v2.5.0 9622027cfdc7 11 days ago 228MB
goharbor/redis-photon v2.5.0 9a083b2a368f 11 days ago 158MB
goharbor/trivy-adapter-photon v2.5.0 d09fd9cd6d3f 11 days ago 155MB
goharbor/notary-server-photon v2.5.0 d36bb495692a 11 days ago 115MB
goharbor/notary-signer-photon v2.5.0 2583d6c93a43 11 days ago 112MB
goharbor/harbor-registryctl v2.5.0 70862e0cbb5f 11 days ago 139MB
goharbor/registry-photon v2.5.0 44e6d030ef05 11 days ago 80.8MB
goharbor/nginx-photon v2.5.0 c5f863149003 11 days ago 47.3MB
goharbor/harbor-log v2.5.0 fe824554edac 11 days ago 162MB
goharbor/harbor-jobservice v2.5.0 95908dfefed1 11 days ago 229MB
goharbor/harbor-core v2.5.0 d96c170c3235 11 days ago 206MB
goharbor/harbor-portal v2.5.0 76f465040c9e 11 days ago 55.6MB
goharbor/harbor-db v2.5.0 12d465bbb41a 11 days ago 227MB
goharbor/prepare v2.5.0 635dbac6a2f5 11 days ago 269MB
这个时候我们访问ip,就可以发现登录界面,默认 admin 用户的密码为 Harbor12345
- 创建新项目
根据要求填写数据
- 登录仓库
[root@master harbor]# docker login -u admin -p 123456 127.0.0.1
WARNING! Using --password via the CLI is insecure. Use --password-stdin.
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
Login Succeeded
#这样就是登录成功了
- 上传镜像
#通过docker tag将该镜像标志为要推送到私有仓库
docker tag nginx:latest 127.0.0.1/jiusheng/nginx:latest
#通过 docker push 命令将 nginx 镜像 push到私有仓库中
docker push 127.0.0.1/jiusheng/nginx:latest
这个时候在网页就可以查看到上传的镜像
- 远程链接是仓库
#Docker Registry 交互默认使用的是 HTTPS,但是搭建私有镜 我们使用的是 HTTP 服务,所以与私有镜像交互时出现错误。
[root@node ~]# docker login -u admin -p 123456 http://121.5.38.73
WARNING! Using --password via the CLI is insecure. Use --password-stdin.
Error response from daemon: Get https://121.5.38.73/v2/: dial tcp 121.5.38.73:443: connect: connection refused
#这个时候我们要修改配置文件docker.service
vim /usr/lib/systemd/system/docker.service
#修改如下
[Unit]
*********
[Service]
ExecStart=/usr/bin/dockerd -H fd:// --insecure-registry 121.5.38.73 --containerd=/run/containerd/containerd.sock
#添加如下
--insecure-registry 121.5.38.73 #这里就是你仓库的地址,有端口的带上端口
#结果
ExecStart=/usr/bin/dockerd -H fd:// --insecure-registry 121.5.38.73 --containerd=/run/containerd/containerd.sock
#重启docker服务
systemctl daemon-reload && systemctl restart docker
#链接
[root@node ~]# docker login -u admin -p 123456 121.5.38.73
WARNING! Using --password via the CLI is insecure. Use --password-stdin.
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
Login Succeeded
#这样就登录成功了
- 上传镜像
#这里我们没有镜像,所以下载一个centos镜像
docker pull centos
#查看镜像
docker images
#上传镜像,和之前的操作一样,只是ip不一样
docker tag centos:latest 121.5.38.73/jiusheng/centos:latest
docker push 121.5.38.73/jiusheng/centos:latest
网页即可查看到刚才的镜像
下载命令♾️ shell 代码:
#命令格式喝下
docker pull ip/项目名/镜像
#示例
docker pull 121.5.38.73/jiusheng/centos:latest
docker——compose
Compose介绍
Docker Compose是一个用来定义和运行复杂应用的Docker工具。一个使用Docker容器的应用,通常由多个容器组成。使用Docker Compose不再需要使用shell脚本来启动容器。
Compose 通过一个配置文件来管理多个Docker容器,在配置文件中,所有的容器通过services来定义,然后使用docker-compose脚本来启动,停止和重启应用,和应用中的服务以及所有依赖服务的容器,非常适合组合使用多个容器进行开发的场景。
Compose和Docker兼容性
安装docker-compose
版本发布地址:https://github.com/docker/compose/releases
两种安装方式
- 从github上下载docker-compose二进制文件安装下载最新版的docker-compose文件
#下载最新版的docker-compose文件
sudo curl -L https://github.com/docker/compose/releases/download/1.16.1/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
- 若是github访问太慢,可以用daocloud下载
sudo curl -L https://get.daocloud.io/docker/compose/releases/download/1.16.1/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
- 添加可执行权限
sudo chmod +x /usr/local/bin/docker-compose
- 测试安装结果
$ docker-compose --version
docker-compose version 1.16.1, build 1719ceb
2.pip安装
♾️ shell 代码:sudo pip install docker-compose
docker-compose文件结构和示例
♾️ shell 代码:docker-compose文件结构
docker-compose.yml
#docker-compose.yml里面的内容
version: "3" #version:指定 docker-compose.yml 文件的写法格式
services: #services:多个容器集合
#补充environment:环境变量配置,可以用数组或字典两种方式
redis:
image: redis:alpine #image:指定服务所使用的镜像
ports: #ports:定义宿主机端口和容器端口的映射,可使用宿主机IP+宿主机端口进行访问 宿主机端口:容器端口
#补充 expose:定义容器用到的端口(一般用来标识镜像使用的端口,方便用ports映射)
- "6379"
networks:
- frontend
deploy:
replicas: 2
update_config:
parallelism: 2
delay: 10s
restart_policy:
condition: on-failure
db:
image: postgres:9.4
volumes: #volumes:卷挂载路径,定义宿主机的目录/文件和容器的目录/文件的映射 宿主机路径:容器路径
#depend_on: 规定service加载顺序,例如数据库服务需要在后台服务前运行
#extra_hosts:类似于docker里的--add-host参数 配置DNS域名解析(域名和IP的映射)
- db-data:/var/lib/postgresql/data
networks:
- backend
deploy:
placement:
constraints: [node.role == manager]
vote:
image: dockersamples/examplevotingapp_vote:before
ports:
- 5000:80
networks:
- frontend
depends_on:
- redis
deploy:
replicas: 2
update_config:
parallelism: 2
restart_policy:
condition: on-failure
result:
image: dockersamples/examplevotingapp_result:before
ports:
- 5001:80
networks:
- backend
depends_on:
- db
deploy:
replicas: 1
update_config:
parallelism: 2
delay: 10s
restart_policy:
condition: on-failure
worker:
image: dockersamples/examplevotingapp_worker
networks:
- frontend
- backend
deploy:
mode: replicated
replicas: 1
labels: [APP=VOTING]
restart_policy:
condition: on-failure
delay: 10s
max_attempts: 3
window: 120s
placement:
constraints: [node.role == manager]
visualizer:
image: dockersamples/visualizer:stable
ports:
- "8080:8080"
stop_grace_period: 1m30s
volumes:
- "/var/run/docker.sock:/var/run/docker.sock"
deploy:
placement:
constraints: [node.role == manager]
networks:
frontend:
backend:
volumes:
db-data:
第一个compose程序
- 创建一个目录
mkdir composetest && cd composetest
- 在项目目录中创建一个名为的文件
app.py
并配置。
vim app.py
#添加如下
import time
import redis
from flask import Flask
app = Flask(__name__)
cache = redis.Redis(host='redis', port=6379)
#在此示例中,redis是应用程序网络上的redis容器的主机名。我们使用 Redis的默认端口,6379
def get_hit_count():
retries = 5
while True:
try:
return cache.incr('hits')
except redis.exceptions.ConnectionError as exc:
if retries == 0:
raise exc
retries -= 1
time.sleep(0.5)
@app.route('/')
def hello():
count = get_hit_count()
return 'Hello World! I have been seen {} times.\n'.format(count)
- 在目录中创建另一个名为的文件
requirements.txt
,并添加如下
vim requirements.txt
#添加如下
flask
redis
- 在目录中,创建一个名为
Dockerfile
并配置如下内容
vim Dockerfile
#添加如下
# syntax=docker/dockerfile:1
FROM python:3.7-alpine
WORKDIR /code
ENV FLASK_APP=app.py
ENV FLASK_RUN_HOST=0.0.0.0
RUN apk add --no-cache gcc musl-dev linux-headers
COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt
EXPOSE 5000
COPY . .
CMD ["flask", "run"]
这告诉 Docker:
- 从 Python 3.7 映像开始构建映像。
- 将工作目录设置为
/code
. - 设置命令使用的环境变量
flask
。 - 安装 gcc 和其他依赖项
- 安装
requirements.txt
中的 Python 依赖项。 - 向镜像添加元数据以描述容器正在侦听端口
5000
- 将项目中的当前目录复制
.
到镜像中的workdir.
。 - 将容器的默认命令设置为
flask run
.、
- 目录中创建一个名为的文件
docker-compose.yml
并编写如下内容
vim docker-compose.yml
#添加如下
version: "3.9"
services:
web:
build: .
ports:
- "8000:5000"
redis:
image: "redis:alpine"
#定义了两个服务:web和redis.
- 使用 Compose 构建并运行
#使用docker-compose up,构建运行
docker-compose up
[root@node composetest]# docker-compose up
[+] Running 7/7
⠿ redis Pulled 4.2s
#******省略
composetest-redis-1 | 1:M 16 Mar 2022 08:28:19.248 * Ready to accept connections
composetest-web-1 | * Serving Flask app 'app.py' (lazy loading)
composetest-web-1 | * Environment: production
composetest-web-1 | WARNING: This is a development server. Do not use it in a production deployment.
composetest-web-1 | Use a production WSGI server instead.
composetest-web-1 | * Debug mode: off
composetest-web-1 | * Running on all addresses.
composetest-web-1 | WARNING: This is a development server. Do not use it in a production deployment.
composetest-web-1 | * Running on http://172.18.0.3:5000/ (Press CTRL+C to quit)
#查看
[root@node ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f86849da968b composetest_web "flask run" 36 seconds ago Up 35 seconds 0.0.0.0:8000->5000/tcp composetest-web-1
3b4112182774 redis:alpine "docker-entrypoint.s…" 36 seconds ago Up 34 seconds 6379/tcp composetest-redis-1
#验证是否成功启动
[root@node ~]# curl localhost:8000
Hello World! I have been seen 1 times.
- 其他命令
#查看命令docker-compose ps
[root@node composetest]# docker-compose ps
NAME COMMAND SERVICE STATUS PORTS
composetest-redis-1 "docker-entrypoint.s…" redis running 6379/tcp
composetest-web-1 "flask run" web running 0.0.0.0:8000->5000/tcp
#停止命令docker-compose down 或者docker-compose stop
[root@node composetest]# docker-compose down
[+] Running 3/2
⠿ Container composetest-redis-1 Removed 0.2s
⠿ Container composetest-web-1 Removed 10.1s
⠿ Network composetest_default Removed 0.0s
#后台运行
docker-compose up -d
[root@node composetest]# docker-compose up -d
[+] Running 3/3
⠿ Network composetest_default Created 0.0s
⠿ Container composetest-redis-1 Started 0.5s
⠿ Container composetest-web-1 Started 0.5s
#停止并删除
docker-compose down --volumes
root@node composetest]# docker-compose down --volumes
[+] Running 3/2
⠿ Container composetest-redis-1 Removed 0.2s
⠿ Container composetest-web-1 Removed 10.1s
⠿ Network composetest_default Removed 0.0s
[root@node composetest]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
快速部署一个 wordpress博客
- 创建一个目录
mkdir my_wordpress && cd my_wordpress
- 编写docker-compose.yml文件
vim docker-compose.yml
#填写如下
version: "3.9"
services:
db:
image: mysql:5.7
volumes:
- db_data:/var/lib/mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: somewordpress
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: wordpress
wordpress:
depends_on:
- db
image: wordpress:latest
volumes:
- wordpress_data:/var/www/html
ports:
- "80:80"
restart: always
environment:
WORDPRESS_DB_HOST: db
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD: wordpress
WORDPRESS_DB_NAME: wordpress
volumes:
db_data: {}
wordpress_data: {}
- 运行并查看
[root@node my_wordpress]# docker-compose up -d
[+] Running 0/2
⠙ wordpress Pulling
#省略
⠿ Container my_wordpress-db-1 Started 1.1s
⠿ Container my_wordpress-wordpress-1 Started 0.7s
[root@node my_wordpress]# docker-compose ps
NAME COMMAND SERVICE STATUS PORTS
my_wordpress-db-1 "docker-entrypoint.s…" db running 33060/tcp
my_wordpress-wordpress-1 "docker-entrypoint.s…" wordpress running 0.0.0.0:80->80/tcp
访问网页ip,我这里设置的80端口,所以直接ip
快速部署一个Typecho博客
- 构建目录
typecho # 目录,随便什么名字
-docker-compose.yml # docker-compose配置文件
-mysql # mysql数据,配置信息,日志所在目录
-nginx
-default.conf # nginx配置文件
-php
-Dockerfile # php镜像的dockerfile
-www
-build #网站源码,需要创建www及可,网站源码解压得到build文件
- docker-compose.yml配置如下
♾️ yaml 代码:♾️ yaml 代码:MYSQL_ROOT_PASSWORD: root用户密码 MYSQL_DATABASE: 数据库名 MYSQL_USER: 用户名 MYSQL_PASSWORD: 数据库密码
version: "3"
services:
nginx:
image: nginx
ports:
- "80:80"
restart: always
volumes:
- ./www/build:/var/www/html
- ./nginx:/etc/nginx/conf.d
depends_on:
- php
networks:
- web
php:
build:
context: ./php
dockerfile: Dockerfile
restart: always
ports:
- "9000:9000"
volumes:
- ./www/build:/var/www/html
environment:
- TZ=Asia/Shanghai
depends_on:
- mysql
networks:
- web
mysql:
image: mysql:5.7
restart: always
ports:
- "3306:3306"
environment:
MYSQL_ROOT_PASSWORD: asd745201314
MYSQL_DATABASE: typecho
MYSQL_USER: typecho
MYSQL_PASSWORD: asd745201314
volumes:
- ./mysql:/var/lib/mysql
- ./mysql:/var/log/mysql
- ./mysql:/etc/mysql/conf.d
networks:
- web
networks:
web:
- nginx/default.conf配置如下
server {
listen 80;
server_name liuqingzheng.com;
root /var/www/html;
index index.php;
access_log /var/log/nginx/typecho_access.log main;
location ~ .*\.php(\/.*)*$ {
fastcgi_pass php:9000;
fastcgi_index index.php;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info;
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
- php/Dockerfile配置如下
FROM php:7.3.29-fpm
MAINTAINER lqz
RUN apt-get update && docker-php-ext-install pdo_mysql && echo "output_buffering = 4096" > /usr/local/etc/php/conf.d/php.ini
- www/build配置如下
#在www目录下,下载程序包
wget https://github.com/typecho/typecho/releases/download/v1.2.0/typecho.zip
#解压,即可得到build目录
yun install unzip -y
unzip typecho.zip && rm -rf typecho.zip
- 构建并运行
docker-compose up -d
- 打开网页填写数据库
数据库名:typecho
数据库用户名:typecho
数据库密码:asd745201314
数据库root用户密码:asd745201314
数据库地址:mysql
安装提示如下内容
进行如下处理
♾️ shell 代码:#在网站的根目录也就是build目录下创建config.inc.php并配置文件
vim config.inc.php
#代码如下,以实际数据为准,及复制你的
<?php
// site root path
define('__TYPECHO_ROOT_DIR__', dirname(__FILE__));
// plugin directory (relative path)
define('__TYPECHO_PLUGIN_DIR__', '/usr/plugins');
// theme directory (relative path)
define('__TYPECHO_THEME_DIR__', '/usr/themes');
// admin directory (relative path)
define('__TYPECHO_ADMIN_DIR__', '/admin/');
// register autoload
require_once __TYPECHO_ROOT_DIR__ . '/var/Typecho/Common.php';
// init
\Typecho\Common::init();
// config db
$db = new \Typecho\Db('Pdo_Mysql', 'typecho_');
$db->addServer(array (
'host' => 'mysql', #填写的数据库地址
'port' => 3306, #端口
'user' => 'typecho', #用户名
'password' => 'asd745201314', #密码
'charset' => 'utf8mb4', #编码
'database' => 'typecho', #数据库名
'engine' => 'InnoDB',
), \Typecho\Db::READ | \Typecho\Db::WRITE);
\Typecho\Db::set($db);
#上面的就是我们在yaml文件里面编写的数据。
之后在确认安装就完成了。
命令总结
♾️ shell 代码:使用 Docker 定义和运行多容器应用程序。
用法:
docker-compose [-f <arg>...] [--profile <name>...] [options] [COMMAND] [ARGS...]
docker-compose -h|--帮助
选项:
-f, --file FILE 指定一个备用的撰写文件
(默认:docker-compose.yml)
-p, --project-name NAME 指定备用项目名称
(默认:目录名)
--profile NAME 指定要启用的配置文件
--verbose 显示更多输出
--log-level LEVEL 已弃用且从 2.0 开始无法使用 - 设置日志级别(DEBUG、INFO、WARNING、ERROR、CRITICAL)
--no-ansi 不打印 ANSI 控制字符
-v, --version 打印版本并退出
-H, --host HOST 要连接的守护进程套接字
--tls 使用 TLS;由 --tlsverify 暗示
--tlscacert CA_PATH 仅由该 CA 签名的信任证书
--tlscert CLIENT_CERT_PATH TLS 证书文件的路径
--tlskey TLS_KEY_PATH TLS 密钥文件的路径
--tlsverify 使用 TLS 并验证远程
--skip-hostname-check 不检查守护进程的主机名
客户端证书中指定的名称
--project-directory PATH 指定备用工作目录
(默认:Compose 文件的路径)
--compatibility 如果设置,Compose 将尝试转换 deploy
v3 文件中的密钥到它们的非 Swarm 等效项
命令:
build 构建或重建服务
bundle 从 Compose 文件生成一个 Docker 包
config 验证并查看 Compose 文件
create 创建服务
down 停止和移除容器、网络、镜像和卷
events 从容器接收实时事件
exec 在正在运行的容器中执行命令
help 获取有关命令的帮助
images 镜像列表
kill 杀死容器
logs 查看容器的输出
pause 暂停服务
port 打印端口绑定的公共端口
ps 列出容器
pull 拉取服务镜像
push 推送服务镜像
restart 重启服务
rm 删除停止的容器
run 运行命令
scale 设置服务的容器数量
start 启动服务
stop 停止服务
top 显示正在运行的进程
unpause 取消暂停服务
up 创建并启动容器
version 显示 Docker-Compose 版本信息
用法:docker compose [OPTIONS] 命令
码头工人撰写
选项:
--ansi string 控制何时打印 ANSI 控制字符 ("never"|"always"|"auto") (默认 "auto")
--compatibility 在向后兼容模式下运行 compose
--env-file string 指定备用环境文件。
-f, --file stringArray 编写配置文件
--profile stringArray 指定要启用的配置文件
--project-directory string 指定备用工作目录
(默认:Compose 文件的路径)
-p, --project-name 字符串 项目名称
命令:
build 构建或重建服务
convert 将撰写文件转换为平台的规范格式
cp 在服务容器和本地文件系统之间复制文件/文件夹
create 为服务创建容器。
down 停止并移除容器、网络
events 从容器接收实时事件。
exec 在正在运行的容器中执行命令。
images 列出创建的容器使用的图像
kill 强制停止服务容器。
logs 查看容器的输出
ls 列出正在运行的撰写项目
pause 暂停服务
port 打印端口绑定的公共端口。
ps 列出容器
pull 拉取服务镜像
push 推送服务镜像
restart 重启容器
rm 删除停止的服务容器
run 运行命令
start 启动服务
stop 停止服务
top 显示正在运行的进程
unpause 取消暂停服务
up 创建并启动容器
version 显示 Docker Compose 版本信息
运行 'docker compose COMMAND --help' 以获取有关命令的更多信息。
结语
《戏为六绝》 ——杜甫
未及前贤更勿疑,递相祖述复先谁?
别裁伪体亲风雅,转益多师是汝师
最后附上pdf,回复自取。
{hide}
{cloud title="docker" type="lz" url="https://wwu.lanzoub.com/itehe01l6t8b" password=""/}
{/hide}
👍
💖
💯
💦
😄
🪙
👍
💖
💯
💦
😄
🪙
👍
💖
💯
💦
😄
🪙