重学Docker

2021年7月15日 6点热度 0条评论 来源: Howlet

转了云方向,代码都少写了

1. 为什么出现Docker

以前开发项目有开发的环境、测试的环境、还有生产的环境,每经过一阶段就要迁移项目。不同的环境有不同的配置,可能导致不可预估的错误,运维要经常性的改动

世界陷入了混乱,于是上帝说,让Docker来吧,于是一切光明。Dokcer 把初始的环境一模一样地复制过来,那么就消除了协作编码时,我的机器能运行,而其他机器不能运行的困境

Docker是基于Go语言的开源项目,Docker可实现应用层的隔离,共享宿主机内核、而虚拟机是隔离系统,连内核,硬件都是各自模拟的

2. Docker的结构

Docker_Host (宿主机):安装了Docker程序的主机,形式为一个守护进程

Client (客户端):连接docker主机进行操作(与守护进程通信)

Registry (仓库):保存各种打包好的镜像(类似Github)

Images (镜像):软件打包好的镜像,放进仓库中(笔者理解为类,可以派生对象)

Containers (容器):镜像启动后的实例成为容器(笔者理解按照类创建的对象)

3. 卸载、安装

3.1 卸载

# 卸载旧版本
$  sudo yum remove docker \
                  docker-client \
                  docker-client-latest \
                  docker-common \
                  docker-latest \
                  docker-latest-logrotate \
                  docker-logrotate \
                  docker-engin
                  
# 卸载新版本
$ sudo rm -rf /var/lib/docker
$ sudo rm -rf /var/lib/containerd
$ yum remove docker-ce docker-ce-cli containerd.io

主机上的镜像、容器、卷、自定义配置是不会自动删除的需要手动

3.2 配置Docker库

$ yum install -y yum-utils
$ yum-config-manager \ 
	--add-repo \ 
	https://download.docker.com/linux/centos/docker-ce.repo

安装yum工具包,里面包含yum-config-manager,用来设置yum配置

首次安装Docker需在yum中设置的Docker存储库,之后就可从Docker存储库中安装和更新

3.3 安装

$ yum install docker-ce docker-ce-cli containerd.io

docker-ce引擎(社区免费版)、cli(可远程连接守护进程)、containerd(提供容器管理服务)

3.4 启动

$ systemctl start docker
$ systemctl enable docker
$ docker version	# 查看版本

3.5 设置镜像加速

$ vim /etc/docker/daemon.json

# 去阿里云开发平台查看自己的仓库地址
{
  "registry-mirrors": ["https://XXXXXXXX.mirror.aliyuncs.com"]
}

$ systemctl daemon-reload
$ systemctl restart docker

梯子加速你懂的 —_—

4. 启动案例

下面举几个例子,现在看不懂没关系,看看使用Docker有多快速

4.1 Hello-World

# 输入命令并执行
$ docker run hello-world

阅读运行之后的说明,里面有步骤与相关信息,对理解其原理有很大的帮助

4.2 启动Tomcat

以前运行Tomcat,要安装设置启动jdk、tomcat,期间还需到weget、tar等命令

现在使用了Docker,只需几个命令

# 拉取镜像,不加后面的标签默认拉取最新版
$ docker pull tomcat

# 启动容器
$ docker run -d -p 8080:8080 --name mytomcat -v /root/aria2-downloads:/usr/local/tomcat/webapps tomcat

# 访问
# 访问结果是404,因为镜像的webapps空的,意思是没有html页面给我们访问
# 其实最新的镜像将wepapps改名为webapps.dist,那么我们只需复制内容过去就可
# 不怕有解决方法,还是按着下面步骤输入:
$ docker exec -it  mytomcat  /bin/bash
$ cp -r webapps.dist/* webapps
$ exit

# 再次访问即可

4.3 启动MySQL

去Docker官网搜索MySQL,跟着其步骤走 MySQL的Docker地址,下面的密码设置官网也都有详细介绍

因为使用Navicat连接时会发生身份验证器错误,所以我们得进去容器修改验证器插件

# 启动并设置密码
$ docker run -d -p 3306:3306 --name howlmysql -e MYSQL_ROOT_PASSWORD=123456 mysql

# 进入容器内部
docker exec -it containerId /bin/bash

# 登录容器内的MySQL
mysql -uroot -p 123456

# 修改身份验证插件
ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY '123456';

# 刷新权限
flush privileges;

4.4 启动Aria2

一个基于命令行的下载工具

# Aria2本体
$ docker run -d \
  --name aria2-pro \
  --restart unless-stopped \
  --log-opt max-size=1m \
  -e PUID=$UID \
  -e PGID=$GID \
  -e UMASK_SET=022 \
  -e RPC_SECRET=<secret> \
  -e RPC_PORT=6800 \
  -p 6800:6800 \
  -e LISTEN_PORT=6888 \
  -p 6888:6888 \
  -p 6888:6888/udp \
  -v $PWD/aria2-config:/config \
  -v $PWD/aria2-downloads:/downloads \
  p3terx/aria2-pro
  
  
# Web界面
$ docker run -d \
  --name ariang \
  --log-opt max-size=1m \
  --restart unless-stopped \
  -p 6880:6880 \
  p3terx/ariang

5. 常用命令

5.1 帮助命令

$ docker version
$ docker info			 # 更详细信息,客户端,服务器运行状况
$ docker [命令] --help    # 帮助命令

5.2 镜像命令

$ docker pull name[:tag]     # 拉镜像
$ docker rmi name|id		 # 删镜像
$ docker images  			 # 列出本地镜像
$ docker search  			 # 官网查找镜像

5.3 容器命令

# 新建并启动容器
$ docker run [可选参数] image
    --name 				# 重命名
    -d					# 守护容器后台
    -p					# 端口映射
    -v					# 文件挂载
    -i					# 交互模式
    -t					# 分配一个伪终端,后面跟分配的终端 /bin/bash
    -e					# 环境配置
    --rm				# 用完就删包括卷,测试用(docker run --rm -it -p 80:80 nginx)
    --restart=always	# docker重启,容器也会跟着启动


# 列出正在运行的容器
$ docker ps [可选参数]
    -a 					# 显示包括未运行的
    -l 					# 显示最近创建的容器
    -n					# 显示最近创建的n个容器
	-q					# 只显示id


# 生命周期命令
$ docker start name|id
$ docker restart
$ docker stop
$ docker kill
$ docker rm [-f]		# 强制删除运行中的容器


# 容器交互命令
$ docker exec 			# 在运行的容器里执行命令
$ docker exec -it id /bin/bash # 进入容器开一个新的终端,exit后不会停止容器运行
$ docker attach id 		# 进入正在执行的终端
$ ctrl + P + Q			# 交互中容器不停止退出
$ docker exit 			# 交互中停止容器并退出


# 快捷操作
$ docker container prune  删除所有容器
$ docker rmi $(docker images -q) 删除所有镜像
$ docker rm $(docker ps -aq)

5.4 其他命令

$ docker logs id		# 查看容器的日志
$ docker top id		 	# 查看容器里运行的进程
$ docker inspect id 	# 查看镜像详细信息(层、挂载目录)
$ docker cp id:容器路径 宿主机路径			# 拷贝容器文件到宿主机
$ docker cp 宿主机路径 id:容器路径			# 拷贝宿主机文件到容器
$ docker volume	create|inspect|ls|prue|rm # 数据卷操作
$ docker build	 id		# 由dockerfile生成镜像
$ docker history id		# 查看镜像如何构建
$ docker save id		# 备份镜像成.tar文件
$ docker load id		# 加载备份镜像.tar文件,建议上传仓库

6. Dockers和虚拟机的区别

6.1 虚拟机

模拟出完整的计算机系统(Guest OS),模拟的系统都是完全隔离的,且运行在监视器(Hypervisor)中,这个监视器是软件、硬件或固件

Infrastructure (基础设施):是硬件设施,理解为主机,即笔记本,云服务器

Host Operating System (主机操作系统):是主机的物理操作系统,即日常说的操作系统,Linxu、Windows

Hypervisor (虚拟机监视器):是运行在基础物理服务器和虚拟操作系统间的中间软件层,各应用和虚拟系统可共享硬件

Guest OS (宿主系统):虚拟的操作系统,虚拟机内部运行的操作系统,有完整的硬件和内核(Docker是共享)

Bins/Libs (命令/资源):二进制命令和资源库

APP (应用程序):用户安装的程序

缺点:要运行几个隔离的应用,就要监视器启动几个宿主系统,也就是几个虚拟机。虚拟机模拟了多个隔离的系统,占用了很多的硬盘、CPU、内存,所以启动也很缓慢。

6.2 Docker

Docker是运行容器的引擎,我们将 操作系统的基础库文件、应用程序、所需的依赖等打包到镜像中,然后通过镜像创建容器(类和对象),而容器就在Docker中运行

Docker Daemon (守护进程):守护进程取代Hypervisor,是个进程,负责管理Docker容器

守护进程与宿主机通信,为容器分配资源

使用宿主机的硬件资源,无需虚拟化硬件资源,所以容器无需加载内核,因此是秒级

Docker使用了cgroup + namespace,前者限制资源集,后者限制可访问权限

Docker是Client-Server结构,守护进程在宿主机上,客户端socket连接进程管理运行在主机上的容器

6.3 对比

虚拟机:彻底隔离整个运行环境,每个运行的虚拟系统都是完全隔离的

Docker:隔离不同的应用程序,比如数据库,后端,前端等

比对项 Container(容器) VM(虚拟机)
启动速度 秒级 分钟级
运行性能 接近原生 有所损失
磁盘占用 MB GB
数量 成百上千 一般几十台
隔离性 进程级别 系统级别
操作系统 只支持Linux 几乎所有
封装程度 只打包项目代码和依赖关系,共享宿主机内核 完整的操作系统

7. 图形化界面

笔者了解到的图形化管理工具是Portainer,也是在Docker上运行的程序,建议跟着仓库文档走

# 必须挂载
$ docker run -d -p 9000:9000 --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer-ce

具体各位去摸索一下把~

8. 镜像 image

镜像一种轻量级、可执行的独立软件包,用来打包软件的运行环境和基于运行环境开发的技术。它包含运行某个软件需要的所有内容(包括代码、运行库、环境变量和配置文件)

8.1 联合文件系统

联合文件系统(UnionFS):是一个分层的、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层叠加(类似Git),同时可以将不同目录挂载到同一虚拟文件系统下(-v 文件挂载)

UnionFS是Docker镜像的基础,镜像可以通过分层来进行继承(分层可以共用),基于基础镜像可以制作各种具体的应用镜像

一次同时加载多个文件系统,但从外面看只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有的底层文件和目录

8.2 镜像加载原理

Docker使用UnionFS进行分层,底层是bootfs文件系统(bootloader加载最基础的内核、kernvel)

bootfs的上一层是rootfs,也就是 /dev,/bin,/etc等标准目录和文件

不同的镜像中有相同的分层,那宿主机只需在磁盘、内存中保存一份,这些镜像共享这些分层

8.3 镜像层的叠加

假如我们在Docker上安装tomcat,首先底层是bootfs层,然后在上面安装centos (rootfs),意思是修改了文件系统,那就会叠加一层文件系统、依次类推,还有jdk8层、tomcat层。最终打包成tomcat这个镜像,对外则是一个整体

镜像都是只读的,当容器启动时,一个新的可写层被加载到镜像的顶部(容器层,之下叫镜像层)

若我们在容器层删除了文件,那么会生成一个wihteout文件,将对应的下层文件隐藏掉

8.4 提交生成镜像

上面tomcat的案例我们已经修改过webapps的内容,因修改了联合文件系统,所以可作为一次提交来层层叠加

# 提交到本地仓库,没有add行为了
# name[:tag] 是 自己命名的 镜像名[tag] 作为镜像名
$ docker commit -m "提交信息" -a "作者" id name[:tag]
# eg:
$ docker commit -m "add webapps files" -a "Howl" 9c8524bxxxx  mytomcat:1.0


# 然后就可看到自己打包的镜像了
$ docker images

9. 数据卷

数据卷(volume)是由docker挂载到容器(不属于UFS)存在于一个或多个容器中的目录或文件,因此能绕过UFS一些用于持续存储或共享数据的特性

卷的出现是为了数据的持久化和同步操作,其完全独立于容器的生存周期,因此在删除容器时其挂载的数据卷不会被删除。简单来说:使容器和宿主机共享独立于docker生命周期的数据、亦或者:独立于docker生命周期的目录挂载

特点:

  • 数据卷可以容器之间共享或重用
  • 卷中的更改直接生效
  • 卷中的更改不会包含在镜像的更新中
  • 数据卷的生命周期持续到没有容器使用为止

9.1 具名、匿名挂载

数据卷的默认地址 /var/lib/docker/volumes/xxx

$ docker run -v /宿主机绝对路径:/容器内目录 name[tag]	# 具名挂载(不加"/",在默认地址下起个名字而已)
$ docker run -v /容器内目录	name[tag]				 # 匿名挂载,宿主机用默认地址(会生成唯一的32位id)

# 还有只读,读写权限
$ docker run -v /宿主机绝对路径:/容器内目录:ro|rw name[tag]


# 还有先创建数据卷,后面再挂载
$ docker volume create mysql_data
$ docker run -d -p 3306:3360 -v mysql_data:/root/mysql_data

9.2 Dockerfile挂载

这里说明有这种挂载方式,什么是dockerfile下面会讲

$ FROM centos

# 没有"/",是匿名挂载,宿主机的默认地址
# 容器内直接在根目录下
$ VOLUME ["volume01","volume02"]

$ CMD echo "----Howl write dockerfile----"

$ CMD /bin/bash

9.3 容器数据卷

容器数据卷是用于容器间的数据共享,操作方式还是命令行: --volume-from

# centos01就叫数据卷容器
$ docker run -d --name centos01 howl/centos:1.0

$ docker run -d --name centos02 --volume-from centos01 howl/centos:1.0

这是数据卷,不和容器同生命周期,所以哪怕父容器删了,其余容器也能访问同步

10. Dockerfile

Dockerfile是有一系列命令和参数的脚本,通过这个脚本我们可以构建一个镜像

10.1 Dockerfile指令

指令必须都是大写,从上往下执行,且每个指令都会创建一层(可用&&将命令连起来只生成一层)

命令 语法 解释
FROM FROM image[:tag] 指定基础镜像,必须第一条。FROM scratch表示不以任何镜像为基础
MAINTAINER 维护者信息
RUN 镜像构建时需要执行的命令
ADD 复制本地压缩文件,会自动解压
WORKDIR 镜像工作目录
VOLUME 设置容器卷
EXPOSE 指定堆外端口
CMD 指定容器运行中的命令,会被覆盖
ENTRYPOINT 指定容器启动时运行的命令,可以追加命令
ONBUILD 当构建一个被继承Dockerfile时会运行该指令
COPY COPY 宿主文件地址 容器文件地址 将文件拷贝到镜像中
ENV 构建时设置环境变量

10.1 编写Dockerfile

举例做个tomcat镜像,需要准备tomcat压缩包、jdk压缩包、readme文件

$ FROM centos
$ MAINTAINER howl

$ COPY readme.txt /usr/local/readme.txt
$ ADD jdk-8u291-linux-x64.tar.gz /usr/local
$ ADD apache-tomcat-8.5.68.tar.gz /usr/local

$ RUN yum -y install vim

$ ENV MYPATH /usr/local
$ WORKDIR $MYPATH

# JAVA_HOME 目录安装之后才知道
$ ENV JAVA_HOME /usr/local/jdk1.8.0_291
$ ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
$ ENV CATALINA_HOME /usr/local/apache-tomcat-8.5.68
$ ENV CATALINA_BASH /usr/local/apache-tomcat-8.5.68
$ ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib

$ EXPOSE 8080

$ CMD /usr/local/apache-tomcat-8.5.68/bin/startup.sh && tail -F /usr/local/apache-tomcat-8.5.68/bin/logs/catalina.out

每条指令都会创建一个新的镜像层,并对镜像进行提交

若构建名为Dockerfile那么就会自动查找,不用-f去指定了

Docker运行得有前台应用在运行,不然会自动结束,tail就是为了前台运行,比如top等命令

注意:根据linux位数,arm,aarch64来安装jdk,笔者安装错了,走了很多弯路

10.2 Build制作镜像

# -f 指定dockerfile的路径
# -t 生成的镜像名字[:tag] 生成镜像的地址
# . 表示当前目录
$ docker build -t howl/tomcat .

10.3 运行制作的镜像

$ docker run -d -p 8080:8080 howl/tomcat

有个注意的地方,webapps下要新建目录才能访问的,不能放入已有文件夹内,也不能直接放入webapps里面

10.4 发布镜像

镜像的发布有两种途径,分别是:

  • DockerHub
# 首先需要登录
$ docker login -u loadingkiller
$ Password: "输入密码"

# 推送名字得是自己DockerHub上的账号名,所以得先改标签
# 本来 howl/centos 改成 loadingkiller/tomcat
$ docker tag howl/tomcat:latest loadingkiller/tomcat:1.0

# 推送,速度慢等吧
$ docker push loadingkiller/centos:1.0

  • 阿里云镜像仓库

进入阿里云镜像管理可以创建镜像仓库,然后跟着里面的提示走

# 登录
docker login -u=XXX registry.cn-hongkong.aliyuncs.com

# 选择分支对应关系
docker tag [ImageId] registry.cn-hongkong.aliyuncs.com/howlet/mytomcat:[镜像版本号]

# 推送上去
docker push registry.cn-hongkong.aliyuncs.com/howlet/mytomcat:[镜像版本号]

# 拉取
docker pull registry.cn-hongkong.aliyuncs.com/howlet/mytomcat:[镜像版本号]

    原文作者:Howlet
    原文地址: https://www.cnblogs.com/Howlet/p/15013163.html
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系管理员进行删除。