1、Docker是什么
Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。Docker的目标是实现轻量级的操作系统虚拟化解决方案,Docker的基础是Linux容器(LXC)等技术。(摘自《Docker技术入门与实战》)
2、容器化和虚拟化
下面从部署一个项目的角度来理解一下容器化和虚拟化的区别。
首先传统方式部署一个项目,速度慢,成本高,系统资源利用率低,不利于迁移扩展。引入虚拟化技术之后能够提高系统资源利用率,而且相对容易扩展,但是虚拟机还是比较重的,占用太多物理资源,移植性差。而使用docker容器,系统资源利用率很高,而且基本不消耗额外的系统资源,应用性能高。
Docker相比传统虚拟化方式具有众多的优势。见下表(摘自《Docker技术入门与实战》):
特性 | 容器 | 虚拟机 |
---|---|---|
启动 | 秒级 | 分钟级 |
硬盘使用 | 一般为MB | 一般为GB |
性能 | 接近原生 | 弱于 |
系统支持量 | 单机支持上千个容器 | 一般为几十个 |
3、docker的安装
首先先搞个CentOS7的虚拟机,可以使用VMware也可以用Vitrual Box,我这里使用后者,centos上可以直接使用yum命令安装。
3.1、步骤
第一步:
设置docker仓库
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
阿里云镜像仓库:
第二步:安装docker
yum install -y docker-ce docker-ce-cli containerd.io
docker-ce是社区版本,docker-ce-cli是客户端。
第三步:测试安装是否成功
systemctl start docker
docker run hello-world
3.2、Docker基本命令
- 启动docker systemctl start docker
- 重启docker systemctl restart docker 或者service docker restart
- 关闭docker systemctl stop docker 或者service docker stop
- 查看docker版本信息 docker version
- docker详细信息 docker info
- 查看containers占用的资源情况 docker stats
4、Image和Container
4.1、Image
4.1.1概念
镜像是一个轻量级的,独立的,可执行的软件软件包,其中包含运行应用程序所需的一切。简单来说就是一个模板,模板一般不会修改,它是只读的。就像是Java中类的概念,通过image可以创建很多实例,这些实例就是container。
下面这张图对理解Image来说很有帮助。也就是说Image是由一层一层的layer组成的,从最底层的操作系统到虚拟机再到应用所依赖的库和可执行文件组成的。
4.1.2、Dockerfile
我们可以通过docker bulid命令和Dockerfile文件来创建一个镜像。了解一下Dockerfile中的语法(下面代码没有什么关联)
FROM 表示指定基础镜像,比如:
FROM openjdk:8
RUN 表示在镜像内部执行一些命令,比如配置环境、安装软件等。比如:
RUN groupadd -r mysql && useradd -r -g mysql mysql
ENV 表示设置变量的值,使用这个变量的方式为$(变量名),比如:
ENV MYSQL_MAJOR 8.0
LABEL 表示设置镜像标签,比如:
LABEL author="justtry"
LABEL email="202829@qq.com"
VOLUME 指定数据挂载的目录,意思就是应用数据在容器中保存的位置,用于持久化数据。比如:
VOLUME /var/lib/mysql
COPY 将主机的文件复制到镜像内,如果目录不存在,自动创建所需目录,但是并不会提取和解压文件,比如:
COPY zkServer.sh /usr/local/bin
ADD 将主机的文件复制到镜像内,和COPY类似,可以对压缩文件进行提取和解压,比如:
ADD application.xml /etc/myconf/
WORKDIR 切换工作目录,若不存在则创建,比如:
WORKDIR /usr/local/tomcat
CMD 容器启动的时候默认执行的命令,若有多个CMD命令,则最后一个生效,比如:
# 格式一:like an exec, this is the preferred form
CMD ["executable","param1","param2"]
# 格式二:as a shell
CMD command param1 param2
# 当Dockerfile指定了ENTRYPOINT,那么使用下面的格式:作为ENTRYPOINT的缺省参数
CMD ["param1","param2"]
ENTRYPOINT 设置容器启动时执行的操作,和CMD类似。
# 格式一:like an exec, this is the preferred form
ENTRYPOINT ["executable", "param1", "param2"]
# 格式二:as a shell
ENTRYPOINT command param1 param2
EXPOSE 指定镜像要暴露的端口比如:
EXPOSE 3306
4.1.3、Image常用命令
- 查看所有images
- docker images
- docker image ls
- 删除镜像(镜像如果被使用或者关联使用,就要逐步关闭和删除)
- docker image rm imageid
- docker rmi -f imageid
- docker rmi -f $(docker image ls)
- 运行镜像 docker run -d --name mytomcat -it -p 9090:8080 --memory 100M --cpu-shares 10 --network tomcat-net -v /tmp/tomcat:/var/lib/ tomcat
- -d 表示后台运行
- –name 给生成的container起个名字
- -it 交互式运行
- -p 指定centos和container的端口映射
- -v volume参数,持久化用的,指定centos上的某个目录和container中的数据存放目录的绑定关系
- –network 使用什么网络
- –memory 内存限制
- –cpu-share cpu权重
- 发布镜像
- 发布到docker官网仓库
- docker login 登录docker
- docker tag [待推送镜像] [docker id/仓库名称/推送到仓库后的镜像名称]:[版本号]
- docker push [docker id/仓库名称/推送到仓库后的镜像名称]:[版本号]
- 发布到阿里云镜像仓库(参数含义和上面的一样)
- docker login --username=[阿里云账号] registry.cn-hangzhou.aliyuncs.com
- docker tag vim-mycentos-image registry.cn-hangzhou.aliyuncs.com/future_shh/vim-cent
- docker push registry.cn-hangzhou.aliyuncs.com/future_shh/vim-centos
- 发布到harbor私有仓库【待补充】
- 发布到docker官网仓库
- 获取镜像 docker pull imagename:[version]
4.2、Container
4.2.1、概念
Docker通过容器来运行应用,容器由镜像获得,我们知道Image是由一层一层的layer组成的,那么Container就是在其之上再加上一层可写层。容器就像是一个微型的Linux机器和运行在其中的应用程序。通过下面这张图来理解:
另外,我们也可以通过Container来反推出取一个Image,就像Java中的反射一样,但是这种方式生成Image过程中是不能看到具体的过程的。命令如下:
docker commit [运行的容器] [生成Image的名称]命令
Container是一种轻量级的虚拟化技术,不用模拟硬件创建虚拟机。Docker基于Linux Kernel的Namespace、CGroups、UnionFileSystem等技术封装成的一种自定义容器格式,从而提供一套虚拟运行环境。
Namespace技术:用来隔离进程、网络和挂载点等
CGroups技术:用来做资源限制,比如内存和CPU等
UnionFileSystem技术:用来做image和container的分层
4.2.2、Container的常用命令
- 查看运行的容器 docker ps
- 查看所有的容器 docker ps -a
- 启动容器 docker start containerid
- 停止容器 docker stop containerid
- 删除容器 docker rm containerid(删除正在运行的容器要加上-f参数)
- 删除所有容器 docker rm -f $(docker ps -a)
- 进入容器 docker exec -it containerid bash
- 查看container日志 docker logs containerid
- 查看容器详情 docker inspect container
- 将container转成image docker commit containerid 转成的image名称
5、Docker Network
5.1、概述
Docker中的网络类型分为三种:bridge、host和none。下面简单了解一下它们的特点和原理,需要知道的是容器本身是一个微型的linux内核,拥有自己的网卡。
首先简单了解一下几个常用的命令:
- 查看网卡
-
给网卡添加/删除IP地址
ip addr add 192.168.0.101/24 dev eth0 ip addr delete 192.168.0.101/24 dev eth0
-
网卡的启动和关闭
systemctl restart network 重启网卡 ifup/ifdown eth0 启动/关闭某个网卡 ip link set eth0 up/down 启动/关闭某个网卡
-
查看docker的network
docker network ls
5.2、三种网络类型
5.2.1、bridge桥接类型
桥接类型是Docker默认的网络类型,它的实现是基于Vitrual Ethernet Pair(veth)技术实现的,是一个成对的端口。通过下面的图来理解容器如何与docker的网络相互连通。
通过docker network inspect bridge命令可以查看到该网络中容器的相关信息
这里只是说明了单机下容器和docker、容器和容器之间的通信,如果容器要访问互联网,docker是通过NAT网络地址转换来实现的。如果多机间的container要实现通信,那么也就是多机之间的网卡要相互连接,具体是通过vxlan技术实现的,需要注意的是多机中的容器本身的ip地址不冲突。
我们也可以创建自己的桥接网络,比如:
这时我们创建一个Tomcat,指定它的网络使用我们创建的my-net网络。然后查看tomcat-net的网络信息,如下:
这时创建的tomcat-net容器是不能ping通在bridge网络下的mytomcat的,需要通过docker network connect my-net mytomcat将mytomcat加入到我们定义的my-net网络中。然后两个在不同网络的Tomcat就可以ping通了,并且它们可以通过名字ping通,这种通过名称来通信在实际应用中是很方便的。
5.2.2、Host主机类型
容器使用Host类型的网络,表示它们共用CentOS的网络。这里我创建一个使用host网络类型的tomcat容器,然后查看它的ip信息,如下:
[root@10 ~]# docker run -d --name host-tomcat --network host tomcat
ec3c26938b9f11ab7135f706b1985bcea78062a12b3cfbb70c54f3fe789d1d00
[root@10 ~]# docker exec -it host-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
inet6 ::1/128 scope host
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 52:54:00:8a:fe:e6 brd ff:ff:ff:ff:ff:ff
inet 10.0.2.15/24 brd 10.0.2.255 scope global dynamic noprefixroute eth0
valid_lft 58950sec preferred_lft 58950sec
inet6 fe80::5054:ff:fe8a:fee6/64 scope link
valid_lft forever preferred_lft forever
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 08:00:27:f4:36:f4 brd ff:ff:ff:ff:ff:ff
inet 192.168.0.101/24 brd 192.168.0.255 scope global dynamic noprefixroute eth1
valid_lft 5547sec preferred_lft 5547sec
inet6 fe80::a00:27ff:fef4:36f4/64 scope link
valid_lft forever preferred_lft forever
5: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:a9:9a:af:9e 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
inet6 fe80::42:a9ff:fe9a:af9e/64 scope link
valid_lft forever preferred_lft forever
23: veth548c8cf@if22: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
link/ether 9a:04:b8:8a:31:9c brd ff:ff:ff:ff:ff:ff link-netnsid 2
inet6 fe80::9804:b8ff:fe8a:319c/64 scope link
valid_lft forever preferred_lft forever
33: vethcf0e106@if32: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
link/ether 7a:60:71:43:4d:2f brd ff:ff:ff:ff:ff:ff link-netnsid 3
inet6 fe80::7860:71ff:fe43:4d2f/64 scope link
valid_lft forever preferred_lft forever
34: br-a7230c53eaee: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:cb:22:e1:85 brd ff:ff:ff:ff:ff:ff
inet 172.18.0.1/16 brd 172.18.255.255 scope global br-a7230c53eaee
valid_lft forever preferred_lft forever
inet6 fe80::42:cbff:fe22:e185/64 scope link
valid_lft forever preferred_lft forever
36: veth20abef9@if35: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master br-a7230c53eaee state UP group default
link/ether 9e:43:fd:66:11:08 brd ff:ff:ff:ff:ff:ff link-netnsid 4
inet6 fe80::9c43:fdff:fe66:1108/64 scope link
valid_lft forever preferred_lft forever
38: veth3e09158@if37: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master br-a7230c53eaee state UP group default
link/ether ae:d8:53:2a:2c:f7 brd ff:ff:ff:ff:ff:ff link-netnsid 2
inet6 fe80::acd8:53ff:fe2a:2cf7/64 scope link
valid_lft forever preferred_lft forever
5.2.3、None类型
None类型的网络只有一个本地回环地址127.0.0.1。比如创建一个网络类型为none的Tomcat容器,查看它的ip信息,如下:
[root@10 ~]# docker run -d --name none-tomcat --network none tomcat
7f462f0724699aab604a40de05ca63f8e073cba5df27fe76f456bda0899c6d28
[root@10 ~]# docker exec -it none-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、Volume和Bind Mounting
Volume是被设计用来持久化数据的,它的生命周期独立于容器,Docker不会在容器被删除后自动删除数据卷,并且也不存在垃圾回收这样的机制来处理没有任何容器引用的数据卷。如果需要在删除容器的同时移除数据卷。可以在删除容器的时候使 用 docker rm -v 这个命令。
这里我创建一个mysql-1的容器,指定它的数据卷为mysql-1,然后通过相关命令查看Volume的具体信息。当我的mysql-1不小心被删除掉之后,它的volume是不会被删除的,这样,我在创建新的mysql容器时,可以指定它的volume为之前的mysql-1,这样数据就不会丢失了。
Bind Mounting是用来同步和共享数据的,下面看一个例子,
Bind Mounting Success!
最后,docker-compose和docker-swarm的内容会在后面补充完整的。