【背景】
开发和运维因为环境不同而导致矛盾
集群环境下每台机器都部署相同的应用
【容器和虚拟机的区别】
启动:容器是秒级,虚拟机启动是分钟级别的
磁盘使用:容器是MB,虚拟机是GB
性能:容器接近原生,虚拟机要弱一点
系统支持量:单机支持上千个容器,虚拟机只支持几个
【docker】
(1)使用C/S架构:Client通过接口与sever进行通信实现容器的架构
(2)Docker是一定要基于Linux系统的,因为docker是基于Linux的LXC、namespace(资源隔离)、cgroup(资源限制)的支持。Docker很重要的一个部分是dockerAUFS(文件挂载系统)
(3)docker在运行的时候必须在顶层可写层有一个正在运行的程序。如果安装一个centos会被docker的机制kill掉。
【docker的images镜像】
将软件环境打包好的模板,用来创建容器的。一个镜像可以创建多个容器。镜像(打包好的环境+应用)运行之后加上了应用就变成了docker所谓的容器,镜像分层结构如下:
1. 镜像基本操作
镜像查看 docker images ls
镜像查找 docker search 镜像名 ,例如docker search tomcat。查找出来的内容,没有命名空间的是官方版本。
镜像下载 docker pull 镜像名:TAG
删除镜像 docker rmi –f 镜像名或者镜像ID:TAG,-f表示强制删除
获取元信息 docker inspect 镜像名或者镜像ID。
【docker的基本操作】
- 配置docker加速器:vi /etc/docker/demo.json。配置之后就会在配置的地址进行镜像的下载。
- 跑起来docker镜像:docker run –name tom –d –p 8080:8080 tomcat:TAG .把镜像跑成一个容器,--name取一个名字,-d后台运行,-p docker安装好之后,会创建自己的网卡,想在本虚拟机外界去访问的话需要用到-p开放:后是容器的端口:前是宿主机的端口。
- docker container ps查看docker正在运行的进程
【容器操作】
- 查看容器是不是正常,docker logs 容器ID/容器名 例如:docker logs tom
- docker container inspect tom也可查看详细信息
- docker container exec –it tom /bin/bash,-i交互模式运行,-t分配一个伪终端,/bin/bash进入到容器的固有写法。
- docker container rm –f 容器名 删除指定容器
【挂载】
Mysql一般要挂载 数据、配置文件、日志
首先在主机上创建相关的文件夹 -> 进行挂载,将容器的mysql conf文件cp到宿主机上docker run –name mysql –d –p 6666:3306 –v /my/mysql/conf:/etc/mysql/mysql.conf.d。
(上面的例子是把主机目录对应到容器目录,前面为主机目录)
【docker网络模式】
(1)桥模式,例如docker run –name t1 –it –network bridge –h XXXXXXX ---dns 8.8.8.8 –rm busybox
(2)主机HOST模式,例如docker run ---name tom –d –network host tomcat
(3)NONE
(4)container共享另一个容器的network namespace
【docker生成镜像的两种方式】
1. 更新镜像 docker commit 命令
通过现有跑起来的容器,修改内容(配置等)之后退出,重新更新生成一个新的镜像。
docker commit –m=‘描述信息’ –a= ‘作者’ 当前修改的容器名 将要生成的新的镜像名:TAG
2. 直接构建 dockerfile(用来构建镜像的源码)
3. 可以读取dockerfile文件,自动化构建应用镜像
dockerfile就是文本文档(包含了命令,和用户所需要使用的命令和参数)
可以使用docker bulid 的命令去执行命令行命令构建一个自动化过程
dcker build –t pro .
(1)结尾的点指定dockerfile上下文得路径
【dockerfile的格式】
(1)注释#
(2)指令 参数
* 指令不会区分大小写,但是约定俗成指令是大写,参数是小写
(3)dockerfile是按照顺序执行的
(4)dockerfile文件第一行可以是注释,但真正有效的第一行指令一定要是FROM(用来构建镜像指定基础镜像)
【dockerfile常用指令】
(1)dockerfile文件名写成Dockerfile会自动被找到。vim Dockerfile
(2)FROM指定基础镜像,如果没有会直接从dockerhub pull一个出来
FROM 镜像
FROM 镜像:TAG
FROM 镜像@<digest>
(3)MAINTAINER 作者本人的详细信息,可以使任何文本,任何位置,推荐放在FROM之后。即将被废
MAINTAINER 文本
(4)LABEL给镜像指定各种数据
LABEL key=value(可以写多个key value)
(5)ADD 把文件复制到容器部去
ADD 文件来源 复制位置
(6)COPY 从宿主机复制文件到创建的新镜像文件
COPY 要复制的源文件或者目录(可以使用通配符) 目标路径(建议使用绝对路径)负责copy会直接使用workdir
** Add和copy的区别:
Add可以从网络资源直接放进容器,copy只能操作宿主机文件
Add可以直接帮你解压宿主机的tar包,但是网络上下在的不会直接解压
(7)EXPOSE暴露端口,可以指定传输层协议
(8)ENTRYPOINT 在镜像运行为容器执行的命令
类似于cmd,可以在dockerfile中写多个,但只有最后一个会在启动后生效。其余的会在容器内部生效
ENTRYPOINT [参数]
(9)CMD
CMD和ENTERPOINT的区别:
* ENTRYPOINT在执行时不会被docker run所携带的命令参数所覆盖,比如ls之类的参数,而且这些命令行参数会被当做参数传递给ENTRYPOINT指定的程序,但是docker run –entrypoint 参数可以覆盖原ENTRYPOINT
* Docker run命令行传入的的参数会覆盖cmd指令内容并且附加到ENTRYPOINT参数后面作为其参数使用
* Dockerfile中可以存在多个entrypoint指令,并且谁在最后,谁就会在run的时候生效
* Dockerfile中如果有完整的cmd指令,且有entrypoint指令,那么谁在最后谁run的时候生效。
(10)WORKDIR接下来所有命令都要使用的目录
WORKDIR 路径path
(11)ENV 配置环境变量
ENV key value
ENV key=value,……(可以有很多)
(12)ARG 配置环境变量
类似ENV,但可以在build的时候通过 --build-arg key=value指定参数,进行传值,如果不传值,那么必须给定一个值
(13)RUN用来指定dockerbuild运行过程中运行的指令,执行shell命令
RUN 命令
(14)ONBUILD 用来在dockerfile中生成一个触发器
【docker分层的概念】
(1)Dockerfile
FROM tomcat:latest
MAINTAINER baidu.com
WORKDIR /usr/local/tomcat/webapps
ADD helloworld ./helloworld
(2)镜像分层
Sending build context to Docker daemon 3.584kB
Step 1/4 : FROM tomcat:latest
---> 1b6b1fe7261e
Step 2/4 : MAINTAINER baidu.com
---> Running in ac58299b3f38
Removing intermediate container ac58299b3f38
---> 5d0da6398f7e
Step 3/4 : WORKDIR /usr/local/tomcat/webapps
---> Running in 1c21c39fc58e
Removing intermediate container 1c21c39fc58e
---> 9bf9672cd60e
Step 4/4 : ADD helloworld ./helloworld
---> 6d67c0d48c20
Successfully built 6d67c0d48c20
Successfully tagged baidu.com/test-helloworld:1.0.0
每一次都会创建一个临时容器,这样做的好处是如果下次再重新构建这个dockerfile的时候,直接从cache中读出已有的容器,不重复创建容器,这样大大节省了构建时间,也不会浪费资源。假设:
FROM tomcat:latest
MAINTAINER baidu.com
WORKDIR /usr/local/tomcat/webapps
ADD helloworld ./helloworld
ADD helloworld ./helloworld2
执行过程是
Step 1/5 : FROM tomcat:latest
---> 1b6b1fe7261e
Step 2/5 : MAINTAINER baidu.com
---> Using cache
---> 5d0da6398f7e
Step 3/5 : WORKDIR /usr/local/tomcat/webapps
---> Using cache
---> 9bf9672cd60e
Step 4/5 : ADD helloworld ./helloworld
---> Using cache
---> 6d67c0d48c20
Step 5/5 : ADD helloworld ./helloworld2
---> 4e5ffc24522f
Successfully built 4e5ffc24522f
Successfully tagged baidu.com/test-helloworld:1.0.1
Step变成了5步,前四步使用了缓存UsingCache,并没有重复创建容器,step1 没有直接使用cache是因为从本地仓库直接拉取了Tomcat:latest当做基础镜像,run的时候重新创建了容器。第五步重新创建了临时容器。
【docker 底层实现】
1、namespace
linux中的pid、ipc、网络等都属于全局的,但是namespace是一种资源隔离方案,在namespace下这些资源相互独立,属于某一个特定的namespace互不干扰,不再是全局的了。每个namespace下的资源相当于一个独立的操作系统内的资源
2、control groups
namespace实现资源隔离后,进程还是可以不受控制的访问系统资源,比如:CPU、内存、磁盘、网络等,为了控制容器中进程对资源的访问。docker采用cgroup(control groups)技术控制容器内进程对资源的消耗。