Docker
Docker 是一个开源的应用容器引擎,基于 Go 语言 并遵从Apache2.0协议开源。
Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口(类似 iPhone 的 app),更重要的是容器性能开销极低
主要利用 linux 内核 namespace 实现沙盒隔离,用cgroup 实现资源限制。
namespace:挂载点 主机名和域名 信号量/消息队列/共享内存 进程号 网络设备/网络栈、端口等 用户和组
作为一种新兴的虚拟化方式,Docker 跟传统的虚拟化方式相比具有众多的优势。
- Docker 容器的启动可以在秒级实现,这相比传统的虚拟机方式要快得多。 其次,Docker 对系统资源的利用率很高,一台主机上可以同时运行数千个 Docker 容器。
- 容器除了运行其中应用外,基本不消耗额外的系统资源,使得应用的性能很高,同时系统的开销尽量小。传统虚拟机方式运行 10 个不同的应用就要起 10 个虚拟机,而Docker 只需要启动 10 个隔离的应用即可。
- 虚拟化技术依赖物理CPU和内存,是硬件级别的;而docker构建在操作系统上,利用操作系统的containerization技术,所以docker甚至可以在虚拟机上运行。
- 虚拟化系统一般都是指操作系统镜像,比较复杂,称为“系统”;而docker开源而且轻量,称为“容器”,单个容器适合部署少量应用,比如部署一个redis、一个memcached。
- 传统的虚拟化技术使用快照来保存状态;而docker在保存状态上不仅更为轻便和低成本,而且引入了类似源代码管理机制,将容器的快照历史版本一一记录,切换成本很低。
- 传统的虚拟化技术在构建系统的时候较为复杂,需要大量的人力;而docker可以通过Dockfile来构建整个容器,重启和构建速度很快。更重要的是 Dockfile可以手动编写,这样应用程序开发人员可以通过发布Dockfile来指导系统环境和依赖,这样对于持续交付十分有利。
- 当然KVM对比于容器也有一个比较大的优势就是可以使用不同的操作系统或内核。所以,举例说,你可以使用微软Azure,同时运行Windows Server2012的实例和SUSE Linux企业级服务器的实例。至于Docker,所有容器都必须使用同样的操作系统和内核。
docker 的镜像概念类似虚拟机的镜像。是一个只读的模板,一个独立的文件系统,包括运行容器所需的数据,可以用来创建新的容器。
一、docker的安装和部署
yum install -y docker-engine-17.03.1.ce-1.el7.centos.x86_64.rpm
docker-engine-selinux-17.03.1.ce-1.el7.centos.noarch.rpm
systemctl start docker.service
docker version ###查看docker的版本
[@foundation66 pub]# docker search ubuntu ### 查询镜像
NAME root DESCRIPTION STARS OFFICIAL AUTOMATED
ubuntu Ubuntu is a Debian-based Linux operating s... 8745 [OK]
[root@foundation66 pub]# docker pull ubuntu ##拉取镜像
Using default tag: latest
latest: Pulling from library/ubuntu
473ede7ed136: Pull complete
c46b5fa4d940: Pull complete
93ae3df89c92: Pull complete
6b1eed27cade: Pull complete
Digest: sha256:29934af957c53004d7fb6340139880d23fb1952505a15d69a03af0d1418878cb
Status: Downloaded newer image for ubuntu:latest
[root@foundation66 pub]# docker images ###查询存在镜像
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu latest ea4c82dcd15a 4 weeks ago 85.8 MB
[root@foundation66 pub]# docker run -it --name vm1 ubuntu #-i:已交互模式进入容器,-t:为容器分配一个伪输入终端,通常一块使用。
root@bd1026faef59:/# ls
bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
root@bd1026faef59:/# exit ##退出容器且关闭,docker ps 查看无
exit
[root@foundation66 pub]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[root@foundation66 pub]# docker ps -a #显示所有的容器,包含未运行的
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
bd1026faef59 ubuntu "/bin/bash" About a minute ago Exited (127) 32 seconds ago vm1
[root@foundation66 pub]# docker start vm1 #启动一个或多个已经被停止的容器
vm1
[root@foundation66 pub]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
bd1026faef59 ubuntu "/bin/bash" 2 minutes ago Up 8 seconds vm1
[root@foundation66 pub]# docker attach vm1 #连接到正在运行中的容器
root@bd1026faef59:/#
root@bd1026faef59:/#
ctrl+p+q 退出容器但不关闭,docker ps 查看有
把之前下载好的镜像导入,创建为容器,并查看容器详情
[root@foundation66 pub]# docker load -i nginx.tar
cdb3f9544e4c: Loading layer 58.44 MB/58.44 MB
a8c4aeeaa045: Loading layer 54.24 MB/54.24 MB
08d25fa0442e: Loading layer 3.584 kB/3.584 kB
Loaded image: nginx:latest
[root@foundation66 pub]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest c82521676580 3 months ago 109 MB
[root@foundation66 pub]# docker run -d --name vm2 nginx #后台运行容器,并返回容器ID
8fab88e2b1323e61f5917f76e060aa1848fdb879cc97b60665a77ef925a13b02
[root@foundation66 pub]# docker inspect 8fab88e2b1323e61f5917f76e060aa1848fdb879cc97b60665a77ef925a13b02
[
{
"Id": "8fab88e2b1323e61f5917f76e060aa1848fdb879cc97b60665a77ef925a13b02",
"Created": "2018-11-17T02:16:33.955407475Z",
"Path": "nginx",
"Args": [
"-g",
"daemon off;"
],
"EndpointID": "42542792e7b4d4f683841d42b9d0be646da595790631b6dee57acddc430c9a4c",
"Gateway": "172.17.0.1",
"IPAddress": "172.17.0.2",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"MacAddress": "02:42:ac:11:00:02"
}
}
在浏览器中查看:
在启动容器的时候,如果不指定对应的参数,在容器外部是无法通过网络来访问容器内部的网络应用和服务的。
运行时做端口映射:将容器的80端口映射到主机的8080端口
查看指定镜像的创建历史
docker exec 在运行的容器中执行命令
docker cp 用于容器与主机间的数据拷贝
docker kill vm1 杀掉一个运行中的容器
docker rm vm1 删除一个或多个容器
docker stop vm1 停止一个运行中的容器
从网上获取镜像
注册阿里云,进入阿里云镜像服务,获取专属加速器地址
数据卷管理
docker run 在创建容器时使用 -v 参数可以挂载一个或多个数据卷到当前运行的容器中,-v的作用是将宿主机上的目录作为容器的数据卷挂载到容器中,使宿主机和容器之间可以共享一个目录。
挂载数据卷到新创建的容器上:
-v 参数可以重复使用,挂载多个数据卷到容器中,冒号前面的是宿主机的目录(本地目录不存在 ,docker 会自动创建),冒号后面的是容器中的挂载目录。
此时修改index.html里的内容,直接会在容器里生效
在浏览器中访问:
默认挂载可以读写数据卷,也可以只读挂载:
data1为默认的读写挂载,而data2是只读挂载,所以不能创建文件,而在物理机上touch文件,容器中可以看到
创建容器镜像
删除vm1,并且再次创建容器名字随意,导入ubuntu:v1,查看文件还在
删除容器,删除镜像
docker diff :检查容器里文件结构的更改
docker logs: 查看容器日志
容器间的互联
--link 参数可以在不映射端口的前提下为两个容器间建立安全连接 --link 参数可以连接一个或多个容器到将要创建的容器。 --link 参数的格式为 --link name:alias,其中 name 是要链接的容器的名称,alias 是这个连接的别名。
docker run -d --name vm1 -p 8080:80 nginx
docker ps -a
docker run -it --name vm2 --link vm1:nginx ubuntu
测试:
网络管理
容器的四种网络模式: bridge 桥接模式、host 模式、container 模式和 none 模式。启动容器时可以使用 --net 参数指定,默认是桥接模式。
Docker 在启动时会创建一个虚拟网桥 docker0,默认地址为 172.17.0.1/16, 容器启动后都会被桥接到 docker0 上,并自动分配到一个 IP 地址。
host 模式
host 模式是 bridge 桥接模式很好的补充。采用 host 模式的 Docker Container,可以直接使用
宿主机的 IP 地址与外界进行通信,若宿主机的 eth0 是一个公有 IP,那么容器也拥有这个公
有 IP。同时容器内服务的端口也可以使用宿主机的端口,无需额外进行 NAT 转换。当然,
有这样的方便,肯定会损失部分其他的特性,最明显的是 Docker Container 网络环境隔离性
的弱化,即容器不再拥有隔离、独立的网络栈。另外,使用 host 模式的 Docker Container 虽
然可以让容器内部的服务和传统情况无差别、无改造的使用,但是由于网络隔离性的弱
化,该容器会与宿主机共享竞争网络栈的使用;另外,容器内部将不再拥有所有的端口资
源,原因是部分端口资源已经被宿主机本身的服务占用,还有部分端口已经用以 bridge 网
络模式容器的端口映射。
container 模式:
这个模式指定新创建的容器和已经存在的一个容器共享一个 Network Namespace,而不是和宿主机共享。
新创建的容器不会创建自己的网卡,配置自己的 IP,而是和一个指定的容器共享 IP、端口范围等。
同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。两个容器的进程可以通过
lo 网卡设备通信。
none 模式:
网络环境为 none,即不为 Docker Container 任何的网络环境。一旦 Docker Container
采用了none 网络模式,那么容器内部就只能使用 loopback 网络设备,不会再有其他的网络资源。
可以说 none 模式为 Docker Container 做了极少的网络设定,但是俗话说得好“少即是多”,在没有网络配置的情况下,作为 Docker 开发者,才能在这基础做其他无限多可能的网络定制开发。这也恰巧体现了 Docker 设计理念的开放。
在 none 网络模式下分配固定 ip:
netns 是在 linux 中提供网络虚拟化的一个项目,使用 netns 网络空间虚拟化可以在本地虚拟
化出多个网络环境,目前 netns 在 lxc 容器中被用来为容器提供网络。使用 netns 创建的网络空间独立于当前系统的网络空间,其中的网络设备以及 iptables 规则等都是独立的,就好像进入了另外一个网络一样。
Dockerfile
制作Docker image 有两种方式:一是使用 Docker container,直接构建容器,再导出成 image 使用;二是使用 Dockerfile,将所有动作写在文件中,再 build 成 image。Dockerfile 的方式非常灵活,推荐使用。
一、使用Dockerfile构建镜像(http服务)
Dockerfile 常用指令:
1. 指定容器运行的用户
该用户将作为后续的 RUN 命令执行的用户。这个命令本实验不需要,但在一些需要指定用
户来运行的应用部署时非常关键,比如提供 hadoop 服务的容器通常会使用 hadoop 用户来启
动服务。
命令使用方式,例如使用 shiyanlou 用户来执行后续命令:
USER shiyanlou
2. 指定后续命令的执行目录
由于我们需要运行的是一个静态网站,将启动后的工作目录切换到/var/www/html 目录:WORKDIR /var/www/html
3. 对外连接端口号
由于内部服务会启动 Web 服务,我们需要把对应的 80 端口暴露出来,可以提供给容器间互
联使用,可以使用 EXPOSE 命令。
在镜像操作部分增加下面一句:
EXPOSE 80
4. 设置容器主机名
ENV 命令能够对容器内的环境变量进行设置:
ENV HOSTNAME sevrer1.example.com
5. 向镜像中增加文件
向镜像中添加文件有两种命令:COPY 和 ADD。
COPY 命令可以复制本地文件夹到镜像中:
COPY website /var/www/html
ADD 命令支持添加本地的 tar 压缩包到容器中指定目录,压缩包会被自动解压为目录,也可以自动下载 URL 并拷贝到镜像,例如:
ADD html.tar /var/www
ADD http://www.westos.org/html.tar /var/www
根据实验需求,我们把需要的一个网站放到镜像里,需要把一个 tar 包添加到 apache 的/var/www 目录下,因此选择使用 ADD 命令:
ADD html.tar /var/www
6. CMD 与 ENTRYPOINT
ENTRYPOINT 容器启动后执行的命令,让容器执行表现的像一个可执行程序一样,与
CMD 的 区 别 是 不 可 以 被 docker run 覆 盖 , 会 把 docker run 后 面 的 参 数 当 作 传 递 给
ENTRYPOINT 指令的参数。Dockerfile 中只能指定一个 ENTRYPOINT,如果指定了很多,
只 有 最 后 一 个 有 效 。 docker run 命 令 的 -entrypoint 参 数 可 以 把 指 定 的 参 数 继 续 传 递 给
ENTRYPOINT。在本实验中两种方式都可以选择。
7. 挂载数据卷
将 apache 访问的日志数据存储到宿主机可以访问的数据卷中:
VOLUME ["/var/log/apche2"]
8.RUN和CMD的
CMD不同于RUN,CMD用于指定在容器启动时所要执行的命令。而RUN用于指定镜像构建时所要执行的命令。
--RUN(安装软件用) RUN可以运行任何被基础image支持的命令
如果基础image指定的是ubuntu,那么RUN中只能使用ubuntu的命令
--CMD(设置容器启动是执行的操作) 可以是自定义脚本,也可是系统命令,
该指令只能出现一次,如果有多条,则只执行最后一条
测试:
在浏览器中输入172.17.0.3
二、docker镜像的封装(sshd服务)
三、docker镜像的封装(nginx)
CMD 与 ENTRYPOINT的区别
ENTRYPOINT 容器启动后执行的命令,让容器执行表现的像一个可执行程序一样,与CMD 的 区 别 是 不 可 以 被 docker run 覆 盖 , 会 把 docker run 后 面 的 参 数 当 作 传 递 给ENTRYPOINT 指令的参数。Dockerfile 中只能指定一个 ENTRYPOINT,如果指定了很多,只 有 最 后 一 个 有 效 。 docker run 命 令 的 -entrypoint 参 数 可 以 把 指 定 的 参 数 继 续 传 递给ENTRYPOINT。
CMD:
ENTRYPOINT:
两者的结合
仓库的搭建:
下载registry镜像
Docker 官方已经把仓库封装为镜像,直接通过启动容器就可以部署完成仓库。目录 /var/lib/registry 是仓库存放镜像的位置
修改镜像的tag,完成后把打了tag的镜像上传到本地镜像。其实就是给这个镜像添加一个带有私有仓库IP的TAG,这样后面才能成功推送到私有仓库
默认 docker 仓库远程推送拉取需要 TLS 加密支持,走的是 https 协议,我们需要进行以下配置:
创建证书文件夹,加入本地解析
生成ssl证书
建立私有仓库并指定证书文件
上传镜像文件到私有仓库
Docker 仓库认证机制:
cd /tmp/docker
mkdir auth
启动registry容器
上传镜像到仓库,失败,需要登陆
登录一次之后,数据会被建立在root下的.docker文件中