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

网易

http://hub-mirror.c.163.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

发表评论

邮箱地址不会被公开。 必填项已用*标注