Docker的使用
为何Docker火了,其解决了一个很大的问题
统一了打包部署的标准
无论是Java还是C++,亦或者是Javascript,都提供了统一的打包标准
类似Window平台的打包成为.exe
使用的命令是docker build … 镜像
其次是有大一统的镜像仓库
可以将所有软件的镜像放到一个指定的地方docker hub
应用运行
进行统一标准的运行方式
docker run 即可进行运行
容器化也进行了相关的资源隔离,资源限制
首先是namespace相关的隔离原理

资源的限制

整体的架构

Docker Host是安装Docker的主机
Docker Daemon是Docker主机上的Docker后台进程,负责处理一切请求
Client 操作Docker主机的客户端工具
Registry 镜像仓库
Images 镜像,即打包好的程序
Containers 容器,镜像启动起来的程序
未来需要实现K8S的CRI 也就是container runtime interface
之后是在Linux上进行Docker的安装
首先需要配置对应的yum源,方便下载对应的安装包
|
sudo yum install -y yum-utils
sudo yum-config-manager \ –add-repo \ http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo |
然后安装docker
|
yum install docker-ce-3:20.10.5-3.el7.x86_64 docker-ce-cli-3:20.10.5- 3.el7.x86_64 containerd.io
#需要注意安装docker的时候,需要带上-版本号.x84_64 |
进行对应的启动
systemctl enable docker –now
接下来在正式拉去镜像之前
我们需要对Registry 进行配置
|
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-‘EOF’ { “registry-mirrors”: [“https://82m9ar63.mirror.aliyuncs.com“], “exec-opts”: [“native.cgroupdriver=systemd”], “log-driver”: “json-file”, “log-opts”: { “max-size”: “100m” }, “storage-driver”: “overlay2” } EOF sudo systemctl daemon-reload sudo systemctl restart docker |
常见的mirrors hub有
Docker中国区官方镜像
https://registry.docker-cn.com
网易
ustc
https://docker.mirrors.ustc.edu.cn
中国科技大学
https://docker.mirrors.ustc.edu.cn
阿里云容器 服务
https://cr.console.aliyun.com/
接下来我们看下如何启动一个镜像
对于启动一个简单的镜像
docker pull nginx
这样是下载了nginx的镜像,这样情况下,nginx下载的镜像版本是最新版的
当然我们可以按照 镜像名:版本名的方式来进行拉取下载
docker pull nginx:1.20.1
而且配置的阿里云这样的地址,只是加速器地址,类似CDN,有的从阿里云服务器上拉取,没有就回源到CDN
其次,镜像中带有alpine的是精简版的,附带的Linux系统是最小化的,所以运行简单

然后利用
docker images查看所有镜像
删除镜像的方式利用的士
docker rmi 镜像名:版本号/镜像id
docker rmi -f $(docker images -aq) #删除全部镜像
还可以删除所有游离的镜像
docker image prune #移除游离镜像 dangling:游离镜像(没有镜像名字的)
启动容器
启动nginx容器
docker run就是对应的命令
常见的option有
-d 后台运行
–restart=always 开机自启
-p 端口映射
docker run –name=mynginx -d –restart=always -p 88:80 nginx
需要注意,如果想要镜像可以长久的运行,就需要一个阻塞的进程,一直进行代理
docker run -it busybox,交互的方式进入当前镜像启动的容器
之后查看正在运行的容器
docker ps
docker ps -a
删除停止的容器
docker rm
docker rm -f 后面的-f是强制删除正在运行的
停止容器
docker stop 容器id/名字
再次启动
docker start 容器id/名字
更新命令
docker update 容器id/名字
在这里,我们顺道说下容器之间的状态转换

上面Running到Stop的话,支持的操作有 kill和Stop
kill是强制kill -9,相当于直接拔电源,而stop则是优雅的停机,正在运行的程序可以处理所有事情再停止
之后则是一个容器的启动方式,有两种,一种我们上面说了,就是run,创建并启动一个容器
其次是 docker create 这是创建一个容器,但是并不启动,需要启动则是使用docker start
所以 docker run -d = docker create + docker start
而容器暂停和启动就是 docker pause和unpause
然后修改容器内部的内容
首先是进容器内部进行修改
docker exec -it 容器id /bin/bash
内部包含的参数还有 -u 指定什么用户 -u 0:0 ,以及表示自己以特权方式进入容器 –privileged
一个终极的使用方式就是 docker exec -it -u 0:0 –privileged mynginx /bin/bash
除了这个exec,还有attach
docker attach 直接获取这个容器的控制台,如何退出,会连带着容器一起退出,很不方便
然后利用-v,将外部数据挂载到内部
docker run –name=mynginx -d –restart=always -p80:80 -v /data/html:/user/share/nginx/html:ro nginx
在挂在的目录之后,还跟着一个:ro,这个:ro指的是readonly
关于容器具体的挂载方式,我们可以做一个实验来检验
比如我们有一个nginx镜像
我们分别以下面三种方式进行挂载,使用的都是-v
一般来说是 -v /root/html:/user/share/nginx.html 这样我们直接绝对路径的方式进行挂载,这样如果我们root下面没有文件,对应的nginx就是直接403
其次是我们使用 -v html:/user/share/nginx.html,这样是创建了一个volume,名字叫做html,进行挂在,并不会对镜像文件进行覆盖,访问仍然还是index.html
最后是 -v /user/share/nginx.html 这是创建了一个匿名卷
关于docker的卷,可以使用docker volume命令进行查看
docker volume ls
所以 -v 宿主机绝对路径:Docker容器内绝对路径 叫做挂载,有空挂载问题
-v 不以/开头的路径 非绝对路径,叫做绑定,会自动管理,避免空挂载问题
关于volume挂载
也是直接-v volume:Docker绝对路径
之后是在修改了镜像内部文件之后,我们可以先看容器文件系统结构的更改
diff 会显示文件的修改,前置位A表示是ADD进去的,D是文件或者目录删除 C是文件或者目录修改
再进行镜像的保存
使用的命令是docker commit
docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
docekr commit -a “author” -m “变化” 容器id atest:v1.0
如果commit提交的新镜像有一个同名镜像,之前的镜像就会被设置为游离镜像
之后是讲镜像在不同的服务器之间的传输
首先如何将一个容器进行导出,可以使用export命令,对应的导入时import命令
但是需要注意的是,export导出后的文件,再利用import导入变为镜像,并不能直接启动
而需要知道之前的启动命令
诸如 docker ps –no-trunc
或者在docekr image inspect中的镜像,将镜像的Entrypoint 的所有和Cmd的链接起来就能得到启动命令
如果是简单的离线传输,可以考虑使用docker的save和load命令
docker save -o test.tar 镜像
这样就导出成为一个tar文件了
在别的服务器上我们可以进行加载这个镜像,利用的是load命令
docker load -i test.tar
进行远程仓库的推送
比如推送到docker hub
需要我们在对应的docker hub上创建对应的仓库
docker login
login后会产生json,存在 ~/.docker/config.json
对应的是docker logout
然后是将旧镜像的名字,改成仓库要求的新版名称
docker tag old名称 新的名称
docker tag guignginx:v1.0 leifengyang/guignginx:v1.0
docker login
docker push 新的名称
docker push leifengyang/guignginx:v1.0
这样就可以从别的机器上下载了
需要注意的士,docker镜像的全名为
docker.io/user/repository:tag
官方的一般为
docker.io/library/redis:latest
自我的为
docker.io/rediscommander/redis-commander:latest
阿里云的则为
registry.cn-hangzhou.aliyuncs.com/library/redis:版本号
类似的命令还有
docker logs 容器名/id
docekr cp
将容器指定的位置的东西复制出来
docker cp 5eff66eec7e1:/etc/nginx/nginx.conf /data/conf/nginx.conf
将容器外部的内容复制到容器里面
docker cp /data/conf/nginx.conf 5eff66eec7e1:/etc/nginx/nginx.conf
SRC 如果是一个文件,而DEST不存在,创建一个文件,名字就是DEST_PATH
DEST_PATH不存在且以/结尾,报错
DEST_PATH 存在并且是文件,替换
DEST_PATH存在并且是目录,复制到目录中,文件名为SRC_PATH的名字
SRC 是一个目录
DEST 不存在就创save建一个那文件
DEST是一个文件,就报错
DEST存在,如果SRC_PATH以 /.结束,就将源文件夹的内容复制到目标中,不以/.结束源文件夹复制到目录中
之后我们说下Docker的构成原理
Docker是具有分层的概念
因为Build的时候利用的是DockerFile
而DockerFile内部具有不同的DockerFile原语
而DockerFile每一句原语都对应着一层
比如下面的DockerFile
FROM ubuntu:15.04
COPY . /app
RUN make /app
CMD python /app/app.py
每一句就是一层,每一层都彼此堆叠
创建新容器的时候,是在基础层上面添加一个新的可写层,对所有的修改都写入这个新的可写层
我们利用docker inspect来查看image的详情

LowerDir中不同的Dir表示的是不同的命令
上面的不同的层,都是镜像相关的层,需要注意的是,镜像的层中文件是不会修改的
如果我们根据镜像创建了一个容器,那么我们会创建了一个新的层次

我们可以利用docker ps -s来查看这个容器的上层的文件系统

上面的size只有0B,
下面才1KB多
这就是容器在镜像上层创建的新的文件系统操作保存的大小
基于此,我们可以说下docker的COW系统,写时复制
COW是一种共享和复制文件的策略,最大程度的提高效率
docker的COW的体现在与,写时复制是一种共享和复制文件的策略,可以最大程度的提高效率
如果文件或者目录位于镜像层吧,我们要在容器层读取,那么可以使用现有的文件
如果需要修改,则需要将文件复制一份到容器层,进行修改
https://docs.docker.com/storage/storagedriver/select-storage-driver/

上面给出了不同Linux内核中可以使用的文件操作系统
我们将说一下overlayFS操作系统
仍然是这样

对于文件系统
分为了image和Container
最终在容器内体现出一个merge的文件系统
这就是容器的联合文件系统
关于容器的可视化界面
可以使用一个镜像来管理诸如Docker Swarm Kubernetes等
使用的命令直接docker启动
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
如果是集群的话,需要在agent部署
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