课程分享:
- 课程分享:Docker+Kubernetes(k8s)微服务容器化实践
课程分享:Kubernetes(k8s)生产级实践指南 从部署到核心应用
课程分享:(极客时间)深入剖析Kubernetes
Docker是一个使用Go语言开发的开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的机器上。Docker的发展速度和火爆程度着实令人惊叹,一发不可收拾,形成了席卷整个IT界的新浪潮。学完本课程你将了解到什么是docker,docker的思想以及诸如镜像,仓库,容器等核心概念。你将学会怎样运行一个容器,如何搭建私有仓库,怎么写dockerfile以及怎样把自己的应用放到容器中运行。docker将会是你的IT路上一笔不小的财富。
Docker 最初是 dotCloud 公司创始人 Solomon Hykes 在法国期间发起的一个公司内部项目,它是基于 dotCloud 公司多年云服务技术的一次革新,并于 2013 年 3 月以 Apache 2.0 授权协议开源,主要项目代码在 GitHub 上进行维护。Docker 项目后来还加入了 Linux 基金会,并成立推动 开放容器联盟(OCI)。
Docker 自开源后受到广泛的关注和讨论,至今其 GitHub 项目 已经超过 5 万 2 千个星标和一万多个 fork。甚至由于 Docker 项目的火爆,在 2013 年底,dotCloud 公司决定改名为 Docker。Docker 最初是在 Ubuntu 12.04 上开发实现的;Red Hat 则从 RHEL 6.5 开始对 Docker 进行支持;Google 也在其 PaaS 产品中广泛应用 Docker。
Docker 使用 Google 公司推出的 Go 语言 进行开发实现,基于 Linux 内核的 cgroup,namespace,以及AUFS 类的 Union FS 等技术,对进程进行封装隔离,属于 操作系统层面的虚拟化技术。由于隔离的进程独立于宿主和其它的隔离的进程,因此也称其为容器。最初实现是基于 LXC,从 0.7 版本以后开始去除 LXC,转而使用自行开发的 libcontainer,从 1.11 开始,则进一步演进为使用 runC 和 containerd。
runc
是一个 Linux 命令行工具,用于根据 OCI容器运行时规范 创建和运行容器。
containerd
是一个守护程序,它管理容器生命周期,提供了在一个节点上执行容器和管理镜像的最小功能集。
Docker 在容器的基础上,进行了进一步的封装,从文件系统、网络互联到进程隔离等等,极大的简化了容器的创建和维护。使得 Docker 技术比虚拟机技术更为轻便、快捷。
下面的图片比较了 Docker 和传统虚拟化方式的不同之处。
- 传统虚拟机技术是虚拟出一套硬件后,在其上运行一个完整操作系统,在该系统上再运行所需应用进程;
- 而容器内的应用进程直接运行于宿主的内核,容器内没有自己的内核,而且也没有进行硬件虚拟。因此容器要比传统虚拟机更为轻便。
对docker有个简单的印象,了解课程的安排。
VM是在硬件层面实现虚拟化
Docker几乎没有使用虚拟化的东西,直接复用了host主机的os,是内核级的虚拟化
(1)Docker容器的启动可以在秒级实现,这相比传统的虚拟机方式要快得多。
(2)其次,Docker对系统资源的利用率很高,一台主机上可以同时运行数千个Docker容器。而且容器除了运行其中应用外,基本不消耗额外的系统资源,使得应用的性能很高,同时系统的开销尽量小。
用形象的类比说明docker的集装箱、标准化、隔离的思想。在用几个工作学习中碰到的问题说明docker解决了哪些问题。
- 解决了运行环境不一致所带来的问题(它会将运行程序的相关配置,要求统一管理)
- 解决耗内存问题,Docker会一开始就为每个程序指定内存分配
- 让快速扩展,弹性伸缩变得简单
一句话概括核心技术就是:去仓库把镜像拉到本地,然后用一条命令把镜像运行起来,把镜像变成容器。
- Build:构建镜像
- Ship:运输镜像
- Run:运行镜像
镜像(Image) 镜像就是一个只读的模板
容器(Container) 运行应用
仓库(Repository) 集中存放镜像文件的场所,分为公有仓库和私有仓库2种形式
构建镜像的目的:可以运行在其他环境中
镜像就是一系列的文件,它可以包括我们应用程序的文件,也可以包括应用环境的文件。
Docker会把这些文件保存到本地,存储方式采用Linux中的联合文件系统的分层概念方式。
镜像可以用来创建Docker容器的。
- 一个镜像可以包含一个完整的操作系统环境和用户需要的其它应用程序。
- 在docker hub 里面有大量现成的镜像提供下载。
- docker的镜像是只可读的,一个镜像可以创建多个容器,每个容器之间相互不干扰。
示例存储方式见下图,由下往上分别是:
- 操作系统的引导
- 具体的Linux操作系统
- 相关软件:tomcat、jdk等
- 应用代码
- 顶层为可写层(属于容器)
Docker利用容器来开发、运行应用
容器是镜像创建的实例。它可以被启动、开始、停止、删除。每个容器都是 相互隔离的、保证安全的平台。容器在运行过程中,如果要写一个镜像里面的文件:就需要将镜像里的文件拷贝到最上层,再进行修改;修改后,当我们应用读一个文件时,从上层开始读,上层没有才往下读;
仓库是集中存放镜像文件的场所。
每个仓库中又包含了多个镜像,每个镜像有不同的标签(tag)。
- 最大的公开仓库是DockerHub(https://hub.docker.com/),存放了数量庞大的镜像供用户下载。
- 国内: Docker - 国内镜像的配置及使用;https://c.163yun.com/hub#/m/library/
- 当然,用户也可以在本地网络内创建一个私有仓库
分别在三种平台上讲解docker的安装。同学可以选择自己的平台观看。
$ uname -r
$ yum remove docker \
docker-common \
docker-selinux \
docker-engine
#yum-util提供yum-config-manager功能
#另外两个是devicemapper驱动依赖的
$ yum install -y yum-utils \
device-mapper-persistent-data \
lvm2
$ yum-config-manager \
--add-repo \
https://download.docker.com/linux/centos/docker-ce.repo
$ yum install -y docker-ce
#查询版本列表
$ yum list docker-ce --showduplicates | sort -r
已加载插件:fastestmirror, langpacks
已安装的软件包
可安装的软件包
* updates: mirrors.163.com
Loading mirror speeds from cached hostfile
* extras: mirrors.163.com
docker-ce.x86_64 17.09.1.ce-1.el7.centos docker-ce-stable
docker-ce.x86_64 17.09.0.ce-1.el7.centos docker-ce-stable
...
#指定版本安装(这里的例子是安装上面列表中的第二个)
$ yum install -y docker-ce-17.09.0.ce
请参考:https://blog.csdn.net/fly910905/article/details/97622433
$ systemctl start docker.service
$ docker version
Client:
Version: 17.09.0-ce
API version: 1.32
Go version: go1.8.3
Git commit: afdb6d4
Built: Tue Sep 26 22:41:23 2017
OS/Arch: linux/amd64
Server:
Version: 17.09.0-ce
API version: 1.32 (minimum version 1.12)
Go version: go1.8.3
Git commit: afdb6d4
Built: Tue Sep 26 22:42:49 2017
OS/Arch: linux/amd64
Experimental: false
第一个实例:用helloworld镜像带入,熟悉docker最基本的两个命令,拉取镜像和运行容器,并讲解背后运行逻辑。
解释:拉取镜像,也就是从docker远程仓库拉去一个镜像到本地,
其中:TAG是可选的(指定版本),OPTIONS为拉取时的一些参数。
解释:查看本机镜像,也可以验证上面的pull是否成功。
REPOSITOR表示镜像名称,:TAG表示版本。
解释:运行镜像,
OPTIONS
、:TAG
同上,
COMMAND
表示这个IMAGE镜像运行起来后要执行的命令,ARG
表示要执行的命令所依赖的参数。
上图共分为三部分,从左至右分别为 Client、Host、Registry。前两个属于本机,Registry在hello-world例子中相当于远程仓库,整个流程为:
- 先向 docker daemon(在Host中)发送拉取镜像请求
- daemon先在本机查找是否由符合版本要求的镜像,如果有,则不会做其他操作;
- 没有的话,daemon就去 Registry中查找,Registry返回相应镜像到本地。
- 先向 docker daemon发送请求,镜像不存在则再执行一次 docker pull过程。
- 然后通过一定方式把镜象变成容器
第二个实例:从运行nginx镜像引出docker网络概念和docker的端口映射,最后运行nginx容器。
- ngnix为持久运行的容器(不同于 hello-world)
- 前台挂起&后台运行(前台运行的话,ctrl+c 即可结束进程,所以最好后台)
- 进入容器内部,观察容器特征
docker pull hub.c.163.com/library/nginx:latest
docker images
,可以看到nginx镜像拉取成功执行 docker run hub.c.163.com/library/nginx:latest 语句,会发现没有任何响应。
另开一个窗口 执行 docker ps语句,该语句会显示正在运行的镜像
执行 docker run -d hub.c.163.com/library/nginx ,在后台运行该镜像,返回的值为容器的ID。
进入容器内部的命令为 docker exec [OPTIONS] CONTAINER COMMAND [ARG...]
解释: 在一个正在运行的容器中执行一条命令。
OPTIONS为执行的参数(可以通过执行 docker exec --help查看)
CONTAINER 为容器名, COMMAND [ARG…]为命令名以及参数
执行 docker exec -it f4 bash
解释:-it为上图的 -i、-t的缩写,f4为容器ID的简写(因为现在在本机上的容器很少,通过23f就足以查找容器),bash为终端命令
Bridge(默认)
bridge模式是Docker默认的网络设置,此模式会为每一个容器 分配Network Namespace、设置IP等,并将一个主机上的Docker容器连接到一个虚拟网桥上。
(1) 利用 veth pair 技术,在宿主机上创建两个虚拟网络接口设备,假设为veth0 和 veth1。而 veth pair 技术的特性可以保证无论哪一个 veth 接收到网络报文,都会将报文传输给另一方
(2) 将 veth0 附加到docker0 网桥上。保证宿主机的网络报文可以发往 veth0
(3) 将 veth1 添加到容器所属的 namespace 下,并被改名为 eth0。
如此一来,保证宿主机的网络报文若发往 veth0,则立即会被 eth0 接收,实现宿主机到容器网络的联通性;同时,也保证 容器单独使用 eth0,实现容器网络环境的隔离性。
缺点:和宿主机以外的网络通信比较困难
Host
不会创建独立的network namespace。Docker容器中的进程处于宿主机的网络环境中,相当于Docker容器和宿主机共同用一个network namespace,使用宿主机的网卡、IP和端口等信息。
但是,容器的其他方面,如文件系统、进程列表等还是和宿主机隔离的。
缺点:容器不再拥有隔离、独立的网络栈,会和宿主机发生资源抢夺
None
没有网络,Docker不会和外界进行通讯。Docker容器拥有自己的Network Namespace,但是,并不为Docker容器进行任何网络配置。也就是说,这个Docker容器没有网卡、IP、路由等信息。需要我们自己为Docker容器添加网卡、配置IP等。
Container
Container模式指定新创建的容器和已经存在的一个容器共享一个Network Namespace,而不是和宿主机共享。
新创建的容器不会创建自己的网卡,配置自己的IP,而是和一个指定的容器共享IP、端口范围等。
同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。两个容器的进程可以通过lo网卡设备通信。
(1) 查找其他容器(即需要被共享网络环境的容器)的网络
(2) 将新创建的容器(也是需要共享其他网络的容器)的namespace,使用其他容器的namespace。
可以用来更好的服务于容器间的通信。可以通过 localhost 来访问 namespace 下的其他容器,传输效率较高。虽然多个容器共享网络环境,但是多个容器形成的整体依然与宿主机以及其他容器形成网络隔离。另外,这种模式还节约了一定数量的网络资源。
缺点:它并没有改善容器与宿主机以外世界通信的情况。
使容器的端口在主机上访问到,采用端口映射,Docker可以将容器里面的端口与主机的端口进行映射,这样就可以通过访问主机端口去访问容器端口。
执行 docker run -d -p 8080:80 hub.c.163.com/library/nginx 运行Nginx镜像,如下图
解释:-d表示后台运行,-p为端口设置,8080为本机端口,80为Nginx容器开放的端口,hub.c.163.com/library/nginx为容器名。
注意:完成上面步骤后,浏览器访问 localhost:32768,会发现访问不到,我们需要 找到Window系统下的Linux环境的地址
docker-machine ip default
,找到Window系统下的Linux环境的地址
另记:上面语句中的-p
替代为-P
,Docker 会随机映射一个 的端口到内部容器开放的网络端口。然后使用docker ps 可以查看映射的端口号。
最后一个实例:创建自己的镜像,引出dockerfile,讲解基本的dockerfile语法。然后讲解私有仓库的搭建。最后分别在两台机器上演示docker的跨平台运行我们的java web项目。
执行
docker pull hub.c.163.com/library/mysql:latest
,拉取mysql镜像,然后执行docker images
查看本地镜像终端执行docker run -d -p 3306:3306 -e MYSQL_ROOT_PASSWORD=000000 -e MYSQL_DATABASE=jpress hub.c.163.com/library/mysql:latest,运行mysql镜像并创建数据库jpress
命令解释详见:library /mysql
1、下载mysql镜像
下载mysql镜像,找到镜像,之后执行
docker pull hub.c.163.com/library/mysql:latest
,之后我们重命名下这个镜像,不然名字太长了,执行
docker tag hub.c.163.com/library/mysql:latest mysql:5.7
,之后执行
docker images
,应该可以看到变化了。
2、运行镜像
执行
docker run -d --name mysql5.7container -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123 mysql:5.7
,注意:123是root用户的密码。之后执行
docker ps -a
,就会看到全部的容器了,可以看到一个名为mysql5.7container的容器。
3、远程连接
之后用navicat进行远程连接,ip地址填宿主主机(即运行者docker的linux)的ip地址,用户名是root,密码是123.
docker pull hub.c.163.com/library/tomcat:latest
拉取tomcat镜像(tomcat镜像会包括jdk镜像),然后docker images
查看本机镜像,tomcat镜像名为hub.c.163.com/library/tomcat
docker build -t jpress:latest .
-t
表示为创建镜像的参数 ,jpress
为镜像名称,latest
为镜像版本。
docker run -d -p 8888:8080 jpress
,运行容器,其中,本机端口号为8888
,jpress开放的端口号为8080
注意:
怎么查看tomcat中应用程序的名字?
- 进入到 jpress镜像内部,
docker exec -it 60 bash
,其中,60
为运行镜像时返回的ID,会发现直接跳转到了 Dockerfile文件中配置的 tomcat目录下cd webapps
下,然后输入ls
展示所有文件,这里就可以看到应用程序的名字了
参考链接:https://www.imooc.com/learn/824
参考链接:https://www.imooc.com/article/16448