什么是容器?
一种虚拟化方案
操作系统级别的虚拟化
只能运行相同或相似内核的操作系统
依赖于Linux内核特性:Namespace和Cgroups(Control Group)
Linux容器技术vs虚拟机
虚拟机部署应用,不但需要包含应用和相关的库,还需要包含操作系统;容器则只需要包含应用和相关的库,节省资源占用。
虚拟机需要模仿硬件的行为,对内存和CPU的损耗非常大;所以,同样配置的服务器,选用容器技术相对于虚拟机可以提供更多的服务能力
什么是Docker?
将应用程序自动部署到容器,采用Go语言开源引擎,基于Apache 2.0开源授权协议发行
Docker特别之处?
Docker在虚拟化容器运行环境中,增加了一个应用程序部署引擎,该引擎目标是提供一个轻量快速的环境,能够运行开发者程序,为方便高效的从开发者环境中部署到测试环境,然后再部署到生产环境。
Docker的目标
提供简单轻量的建模方式
快速运行,去除管理的开销,具有非常高的性能,同一台宿主机可以运行更多的容器,使用户尽可能的利用系统资源
职责的逻辑分离
开发人员只需要关注Docker中运行的应用程序,运维人员只需要关心如何管理容器;docker的目的是加强开发人员写代码的开发环境与运维人员要部署的生产环境的一致性
快速高效的开发生命周期
缩短代码从开发,测试,部署上线运行的周期
鼓励使用面向服务的架构
docker推荐单个容器只运行一个应用程序或者进程,这样就形成了一个分布式的应用程序模型
Docker的使用场景
使用Docekr容器开发、测试、部署服务
Docker在开发环境创建,提交到测试环境,最终进入生产环境。
创建隔离的运行环境
在企业中同一服务的不同版本可能服务于不同的用户,运用Docker可以创建不同的生产环境来运行不同的服务
搭建测试环境
由于Docker轻量化,开发者很容易利用Docker在本地搭建测试环境,用来测试程序在不同系统下的兼容性,甚至搭建集群部署测试
构建多用户的平台即服务(PaaS)基础设施
提供软件即服务(SaaS)应用程序
高性能、超大规模的宿主机部署
Docker Client 客户端
Docker Daemon 守护进程
Docker Image 镜像
Docker Container 容器
Docker Registry 仓库
Docker客户端/守护进程
C/S架构
可本地/远程 访问
Docker Image 镜像
容器的基石,镜像可以叠加
层叠的只读文件系统。低端是引导文件系统
联合加载(union mount)
镜像的结构
Docker Container 容器
通过镜像启动,是Docker的执行单元
启动和执行阶段
写时复制(copy on write)
Docker Registry 仓库
仓库用来保存用户构建的镜像
公有 Docker Hub
私有
Docker依赖的Linux内核特性
(1)Namespances 命名空间
编程语言中, 封装 --> 代码隔离
操作系统中,封装–> 系统资源的隔离,系统资源包括进程、网络、文件系统…
目的:实现轻量级虚拟化服务,也就是容器。在同一个命名空间下的进程,可以感知彼此的变化,而对其他空间的进程变化一无所知,就像一个独立的系统环境
Dokcer使用5个Namespances命名空间
(2)Control groups (cgroups) 控制组
那隔离的资源怎么管理呢?就要用到Control grops 控制组,它是Linux内核提供的可以限制,记录,隔离进程组所使用的物理资源的一种机制。
主要是用来分配资源
提供功能:
Docker容器的能力
安装ubuntu维护的版本
sudo apt-get install -y docker.io
查看docker的版本:sudo docker version
使用非root用户:
1.添加名为docker的用户组:sudo groupadd docker
2.将当前用户添加到docker用户组:sudo gpasswd -a ${USER} docker
3.sudo service docker restart
启动容器:
docker run -i -t --name 镜像名
查看容器:
docker ps [-a] [-l]
docker inspect 容器id或者容器name
自定义容器名:
docker run --name=自定义名字 -i -t IMAGE /bin/bash
重新启动停止的容器:
docker start [-i] 容器名
删除停止的容器:
docker rm 容器名
什么是守护式容器
以守护形式运行容器:
docker run -i -t IMAGE /bin/bash
退出守护式(将交互式容器转到后台):Ctrl+P Ctrl+Q
进入已经退出守护式的容器:docker attach 容器名
(ID或者NAME )
退出:exit
启动守护式容器(后台运行):
docker run -d 镜像名 [COMMAND] [ARG…]
查看容器内部运行情况,看日志:
docker logs [-f] [-t] [–tail] 容器名
-f --follows=trun | false 默认false 实时跟踪
-t --timestamps=true | false 默认false 时间戳
–tail=“all” 指定结尾 返回多少日志
查看容器内进程:
docker top 容器名
在运行中的容器内启动新进程(与run命令相似):
docker exec [-d] [-i] [-t] 容器名 [COMMAND] [ARG…]
停止守护式容器:
docker stop 容器名(发送一个信号给容器,等待容器停止后,会返回容器的名字)
docker kill 容器名( 直接停止容器,快速)
设置容器的端口映射
run [-P] [-p]
-P --publish=true | false 默认为false
docker run -P -i -t ubuntu /bin/bash
-p, --publish=[]
docker run -p 80 -i -t ubuntu /bin/bash
docker run -p 8080:80 -i -t ubuntu /bin/bash
ip :containerPort 指定ip和容器
docker run -p 0.0.0.0:80 -i -t ubuntu /bin/bash
ip:hostPort:containerPort 指定ip 宿主机和容器端口
docker run -p 0.0.0.0:8080:80
Niginx部署流程
创建映射80端口的交互式容器
docker run -p 80 --name web -i -t ubuntu /bin/bash
在容器中安装Nginx
apt-get update
apt -get install -y nginx
按照文本编辑器vim(用来编辑网站和修改nginx配置)
apt-get install vim
创建静态页面
新建一个index.html
mkdir -p /var/www/html
cd /var/www/html
vim index.html
修改Nginx配置文件
whereis nginx 查找nginx安装在哪里
cd /etc/nginx/sites-enabled
vim default
修改静态网站的位置:root /var/www/html
运行Nginx
nginx
ps -ef 查看nginx是否运行起来
验证网站访问
ctrl+P Q 容器在后台运行
docker ps 查看容器映射端口
docker port 查看端口映射情况
docker top web 查看容器的进程运行情况
curl http://127.0.0.1:49167 验证网站访问 (49167是查看到的容器映射端口)
也可以使用容器的IP地址来访问,docker inspect web 查看容器的IP地址,查到IPAddress的地址为xxxx
curl http://xxxx 端口默认是80
Docker Image镜像
使用联合加载技术实现的层叠的只读文件系统,是容器构建的基石。
docker的镜像存储在 /var/lib/docker
可以使用docker info查看镜像存储的位置和docker使用的存储驱动
查看和删除镜像
docker images [OPTSIONS] [REPOSITORY]
-a, --all=false 显示所有镜像,没有仓库名和标签名,即是中间层镜像
-f,–filter=[] 显示过滤条件
--no-trunc=false ID截断显示 ,加上 --no-trunc 显示完整ID(镜像的文件名)
-q, --quitet=false 只显示镜像的ID
REPOSITORY TAG IMAGE ID CREATED
REPOSITORY 仓库:一系列镜像的集合,里面包含独立的镜像。
REGISTRY docker的组件仓库 里面包含很多REPOSITORY
TAG 镜像标签,不同镜像是以标签的形式来区分。REPOSITORY+TAG来构成完整的镜像名字,且对应一个镜像ID
查看镜像的详细信息
docker inspect [OPTIONS] CONTAINER | IMAGE [CONTAINER | IMAGE…]
例如:
docker inspect ubuntu:lastest (仓库:标签)
docker inspect IMAGE ID
删除镜像
docker rmi [OPTIONS] IMAGE [IMAGE…] rmi(remove image)
-f, force=false Force removal of the image
--no-prune=false Do not delete untagged parents
本地镜像和远程仓库互动操作
查找镜像
查看网址 Docker Hub
https://registry.hub.docker.com
docker search [OPTIONS] TERM
–automated=false Only show automated builds
–no-trunc=false Don’t truncate output
-s, --stars=0 Only display with at least x stars
最多返回25个结果
拉取镜像
docker pull [OPTIONS] NAME [:TAG]
-a,–all-tags=false Download all tagged images in the repository
使用 --resistry-mirror 选项,使用国内镜像
1.修改: /etc/default/docker
2.添加:DOCKER_OPTS="–registry-mirror=http://MIRROR-ADDR"
推送镜像
docker push NAME [:TAG]
保存对容器的修改,并再次使用
自定义镜像的能力
以软件的形式打包并分发服务及其运行环境
构建镜像方式
docker commit 通过容器构建
docker build 通过Dockerfile文件构建
使用commit构建镜像
docker commit [OPTIONS] COMTAINER [REPOSITORY] [:TAG]
-a, --author="" Author
e.g., “John Hannibal Smith ha”
-m, --message="" Commit message
-p, --pause=true Pause container during commit
使用dockerfile构建镜像
docker build [OPTIONS] PATH | URL | -
--force-rm=false
--no-cache=false
--pull=false
-q, --quiet=false
--rm=true
-t, --tag=""
Docker的C/S模式
Remote API 与守护进程通信
客户端与守护进程如何通信?通过socket连接
unix://host:port
tcp://host:prot
查看守护进程
ps -ef | grep docker
sudo status docker
使用service命令管理(修改docker的配置后需要用service重启docker服务)
sudo service docker start
sudo service docker stop
sudo service docker restart
docker守护进程的启动选项
docker -d [OPTIONS]
运行相关
-D, --debug=false
-e, --exec-driver=“native”
-g, --graph="/var/lib/docker"
--icc=true
-l, --log-level=“info”
--label=[]
-p, --pidfile="/var/run/docker.pid"
Docker服务器连接相关:
-G, --group=“docker”
-H, --host=[]
--tls=false
--tlscacert="/home/sven/.docker/ca.pem"
--tlscert="/home/sven/.docker/cert.pem"
--tlskey="/home/sven/.docker/key.pem"
--tlsverify=false
RemotAPI相关:
--api-enable-cors=false
存储相关:
-s, --storage-driver=""
--selinux-enabled=false
--storage-opt=[]
Registry相关:
--insecure-registry=[]
--registry-mirror=[]
网络设置相关:
-b, --bridge=""
--bip=""
--fixed-cidr=""
--fixed-cidr-v6=""
--dns=[]
--dns-search=[]
--ip=0.0.0.0
--ip-forward=true
--iptables=true
--ipv6=false
--mtu=0
启动配置文件
/etc/default/docker
如何配置客户端和守护进程的远程访问。客户端和守护进程在不同的机器上
-H 选项
DOCKER_HOST 环境变量
指令格式
注释(#号开头)和指令(大写指令名+参数)
例子:
#First Dockerfile
FROM ubuntu:14.04
MAINTAINER dormancypress “[email protected]”
RUN apt-get update
RUN apt-get install -y nginx
EXPOSE 80
指令:
(1)FROM
FROM
FROM :
必须是已经存在的镜像
基础镜像
必须是第一条非注释指令
(2)MAINTAINER
MAINTAINER
指定镜像的作者信息,包含镜像的所有者和联系信息
(3)RUN
指定当前镜像中运行的命令, 每个RUN命令都会在当前镜像的上层创建一个新的镜像来运行指令
RUN (shell模式)
RUN [“executable”, “param1”, “param2”] (exec模式)
RUN (shell模式)
/bin/sh -c command
RUN echo hello
RUN [“executable”, “param1”, “param2”] (exec模式)
指定其他形式的shell来运行
RUN ["/bin/bash", “-c”, “echo hello”]
(4)EXPOSE
EXPOSE […]
指定运行该镜像的容器使用的端口。但是就算在Dockerfile中指定暴露的端口,在docker运行的时候出于安全考虑,还是要手动指定端口。
docker run -p 80 -d dormacypress/df_test1 nginx -g “daemon off”
(5)CMD
CMD用来提供容器运行的默认命令,和RUN指令类似,都是执行一个命令。RUN命令是在镜像构建过程中执行的,CMD命令是在容器运行时执行的,并且当我们用docker run 命令启动容器时,当我们指定了容器运行时的命令,那么CMD中的指令会被覆盖,不会运行。也就是说CMD指令是用来指定容器运行时的默认指令
(6)ENTRYPOINT
ENTRYPOINT指令和CMD指令相似,但是不会被docker run的命令覆盖。
可以使用docker run --entrypoint覆盖
(7)ADD和COPY
这两个命令都是将文件和目录复制到用dockerfile构建的镜像中,都支持两种参数,来源地址和目标地址。文件和目录的来源可以是本地地址和远程URL,如果是本地地址,必须是构建目录中的相对地址,远程URL,docker不推荐使用。而目标路径是指定镜像中的绝对路径。
区别:
ADD包含类似tar的解压功能
如果单纯复制文件,Docker 推荐使用COPY
ADD …
ADD [""…""] (适用于文件路径中有空格的情况)
COPY …
COPY ["…""] (适用于文件路径中有空格的情况)
(8)VOLUME
VOLUME ["/data"]
用来向镜像创建的容器添加卷,一个卷可以存在于一个或多个容器的特定目录。
(9)WORKDIR
WORKDIR /path/to/workdir (绝对路径)
从镜像创建一个新容器时,在容器内设置工作目录,ENTRYPOINT或者CMD指定的命令都会在这个目录下执行
(10)ENV
设置环境变量,与WORKDIR命令类似,ENV指令可以作用在构建过程中和运行过程中
ENV
ENV =…
(11)USER
USER daemon
镜像为哪些用户运行
USER nginx
USER user USER uid
USER user:group USER uid:gid
USER user:gid USER uid:group
(12)ONBUILD
为镜像添加触发器,当一个镜像被其他镜像作为基础镜像时执行,会在构建过程中插入指令
ONBUILD [INSTRUCTION]
构建过程
1.从基础镜像运行一个容器
2.执行一条指令,对容器做出修改
3.执行类似docker commit的操作,提交一个新的镜像层
4.再基于刚提交的镜像运行一个新容器
5.执行Dockerfile的下一条指令,直至所有指令执行完毕
构建过程中,会删除中间层容器,但是不会删除中间层镜像,可以使用中间层镜像进行调试,查找错误
构建缓存
如果不使用缓存:docker build --noche
查看镜像构建过程
docker history [image]
用ifconfig命令可以查看docker0的网络设备。docker守护进程是通过docker0为容器提供网络连接的各种服务。
这里的docker0是指是Linux的虚拟网桥
网桥是什么?
网桥是数据链路层的一种设备,通过MAC地址,也就是网络设备的物理地址来对网络进行划分,并且在不同的网络之间传递数据。
网桥是一个纯的数据链路层设备,但是Linux的虚拟网桥是有一些不同的特点。
Linux虚拟网桥的特点
可以设置IP地址
相当于拥有一个隐藏的虚拟网卡
我们在docker0的设置中,它实际上有一个独立的IP地址,通常来说,IP地址是网络层协议的内容,不应该出现在二层设备上,但是linux的虚拟网桥,是通用网络设备抽象的一种,只要是网络设备,就能识别IP地址,当虚拟网桥拥有IP后,Linux便可以通过路由表或者IP表规则在网络层定位网桥,这就相当于拥有一个隐藏的虚拟网卡
docker0的地址划分:
docker守护进程在一个容器启动时,实际上它要创建网络连接的两端,一端是在容器中的网络设备,而另一端是在运行docker容器的主机上,打开一个名为veth*的一个接口,用来实现与容器的网络通信
查看网桥,linux需要安装网桥管理程序
sudo apt-get install -bridge-utils
查看网桥设备:sudo brctl show
自定义docker0
修改docker0地址:
sudo ifconfig docker0 192.168.200.1 netmask 255.255.255.0
自定义虚拟网桥
sudo brctl addbr br0
sudo ifconfig br0 192.168.100.1 netmask 255.255.255.0
/etc/default/docker 中添加DOCKER_OPS值
-b = br0
允许所有容器间互联
–icc=true 默认 --icc=false (拒绝连接)
–link
docker run --link=[CONTAINER_NAME]:[ALIAS] [IMAGE] [COMMOND]
允许可定容器间的连接
Docker守护进程的启动选项
--icc=false --iptables=true
--link
ip_forward
–ip_forward=true
ip_forward本省四系统中的一个变量,它的值决定了系统是否会转发流量,当docker启动选项使用了ip_forward时,会将系统的ip_forward设置为1,也就是允许流量转发
查看ip_forward的值
$ sysctl net.ipv4.conf.all.forwarding
iptables
什么是iptables,iptables是与linux内核集成的包过滤防火墙系统,几乎所有的linux发行版本都会包含iptables功能