引言:这次学习回来,技术上给我最深的体会就是互联网团队,基本都是用Linux在进行各种开发,操作.其中特别强调了,所有的应用部署,发布,不使用Docker坚决不允许发布上线.
回来马上看了一下,发现Docker的确是很不错的东西.在Lab推广很有必要.开始学习
参考资料:
官方文档不是很推荐直接读,因为很多概念跟api,解决不了的问题再去查
无论是应用开发者、运维人员、还是其他信息技术从业人员,都有必要认识和掌握
Docker,以在有限的时间内做更多有意义的事。 —–作者附
阿里源一键安装docker:
1 curl -sSL http://acs-public-mirror.oss-cn-hangzhou.aliyuncs.com/docker-engine/internet | sh - #安装完后切换国内加速源,方法自行搜一下
1.初识Docker
**Docker 包括三个基本概念:**镜像(Image),容器(Container),仓库(Repository)
理解了这三个概念,就理解了 Docker 的整个生命周期。
- Docker是C/S架构,由client+守护进程构建
1.镜像(Image)
Docker 镜像是一个层叠,只读的文件系统:(pull或者push的时候就能看出,分几层在下载整合 )
- 最底端是:bootfs
- 其次是rootfs(Debian/Ubuntu)
- 然后利用重要的Union Mount(Linux下的UM技术)技术,一次同时加载多个只读文件系统,在外看来却是一个文件系统.它会将各层文件系统叠加到一起. 下面的镜像称为父镜像,最底层的基础镜像就是bootfs
功能: 除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。镜像不包含任何动态数据,其内容在构建之后也不会被改变。
注意:这里我用的cent 7.2 ,内核是3.10默认,这样安装很多ubuntu的镜像都会启动有问题.
建议做好备份之后升级内核到最新4.4之后.参考:cent7升级内核方法
定制行为用Dockerfile,慎用简单的docker commit
注意:dockerfile是一个文本里面写一些类shell执行语句.然后在当前目录执行的时候
1 | docker build -t nginx:v3 ./ #如果少了./ 可能会报"docker build" requires exactly 1 argument(s). |
- 然后想一下有个关键的两个问题,存储跟网络.类似于虚拟机如何跟宿主机文件交互,网络联通
- 镜像层是只读的,可写层要实例化容器之后才能写入
2.容器(Container)
镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的类和对象一样.
- 简单来说,容器是独立运行的一个或一组应用,以及它们的运行态环境。
- 对应的,虚拟机可以理解为模拟运行的一整套操作系统(提供了运行态环境和其他系统环
境)和跑在上面的应用。
写时复制(docker重要特性):
是docker启动跟执行的阶段,原本镜像是不能直接写入 内容的,docker在容器运行时在最上层开了一个口子让用户写入数据.e.g
- 如果想修改一个文件,这个文件首先会从该读写层下面的只读层复制到读写层,该文件的只读版本依然存在,但是已经被读写层中的该文件副本所隐藏,这就是copy on write
- 每个只读镜像层都是永不会变化的,就像类一样本身是抽象的.(除非你重新修改了镜像源)
- 常见容器操作命令
1 | 1.批量移除所有容器,移除镜像是rmi,慎用 |
守护式容器
什么是守护式容器:
长期运行服务的容器,不需要交互式会话,适合项目运行
1
2
3
4
5
6
7
8
9
10
11
12
13
14ctrl+p-->ctrl+q
docker run -it imageName /bin/bash
如何再次进入这个后台运行的容器
docker attach imageID #前三位
run方式启动后台容器
docker run -d imageName ...
查看容器日志 logs
docker logs imageName # -t 显示时间 -f --follows 更新结果 --tail 显示数量
查看docker容器进程
docker top imageName
3.仓库(Repository/Registry)
Docker很多语法跟git类似,包括概念,这里的仓库可以简单理解为Github/Coding那样存放镜像的集合地
- 分为public/private (类似github),我们可以自建私有Docker Registry(建议)
1 | push公有镜像 |
然后要注意,Dockerfile已经成为比较好的办法,经常缺它会报错.所以建议以后建立镜像都采用Dockerfile的办法.然后再打包之后push倒docker_hub或者其他repository.
2.Docker依赖的Linux特性
Docker内核来说,有两个最重要的依赖Linux特性 : 1. Namespace 2.Control groups (cgroups)
了解这些Linux的内核特性,有助于我们真正理解使用docker,甚至进一步二次开发它.
A.Namespace
很多程序语言就提供了namespace这一概念,其实就是一种封装,达到代码相对隔离的效果.那么类比OS中
Linux也是为了把系统资源进行隔离(e.g. process,network,fileSystem..etc)
实际上,这就是轻量级虚拟化的,可以达到让同一个namespace下的进程感知其它进程的变化,而对其它namespace的变化一无所知.让它觉得自己是一个独立的环境.Docker API提到了5种namespace:
- PID隔离
- Netwok 管理网络接口
- IPC(InterProcess Communication) 跨进程通信
- Mount 管理挂载点
- UTS(Unix Timesharing System) 隔离内核&版本标志
B. Control groups
CG是Linux在2007年2.6内核版本提供的.用来分配资源,来源于Google提出的一种管理机制.
可以说CG(控制组)就是为容器而生,管理容器而用的.它来操控不同的namespace
功能:
- 资源的限制/控制
- 优先级设定(磁盘/网络)
- 资源计量/统计
C. Docker从中获得的能力
通过以上的特性,docker就获得了一些非常强大的功能.
- 文件系统隔离:每个容器都有自己的rootfs
- 进程隔离:每个容器都运行在各自的进程环境中
- 网络隔离:容器间的虚拟网络跟接口ip,都是分开的
- 资源隔离/分组: 通过Control groups,可以将cpu,内存资源独立分配给每个容器.达到利用效率的最大化
3.Docker_Demo
首先就是把一个项目试着打包,然后看它是不是能完全的移植.
- 环境Nginx+Angular’s FE
- Nginx+tomcat+LAMP
(Ⅰ).Nginx跑静态页面
流程:
- 创建交互容器,并映射80端口
- 安装Nginx,vim
- 创建一个静态页面(index.html)
- 修改Nginx配置文件
- 运行Nginx,访问website
1 | A.端口映射 -p 有4种模式 记忆方法:容器端口在最后 |
docker文件传输常用命令:
- 从主机复制到容器 docker cp host_path containerID:container_path
- 从容器复制到主机docker cp containerID:container_path host_path
- 最后拷贝到本地使用scp:
1 | scp username@ip:filePath |
注意:
- 当我们停止一个容器再重启启动,分配的内网IP会改变,映射的端口也可能改变,所以慎重操作一些命令.可以多使用docker aspect imageId 来查看具体信息
(Ⅱ).mysql镜像使用链接
因为mysql用的太多,所以我觉得重点讲一下很有必要,mysql一般两种用法:
- 一种用官方封装好的镜像,内置Debian. 然后跟其他的服务link.
- 另外就是自己在其他的镜像里面封装好mysql服务
1 | 1.拉取镜像略了,下载完了之后以内部13306映射外部的3306端口运行(且初始化密码) |
(Ⅲ).Tomcat跑的Java项目
之前的多个tomcat并行运行在一个系统中,没有任何隔离,非常容易出问题.session共享一堆问题
那么如果使用docker,能不能在保证session共享的基础上配合Nginx组成一个基本的负载均衡呢
4.相关问题
a.构建 Docker 镜像应该遵循哪些原则?
答:整体原则上,尽量保持镜像功能的明确和内容的精简,要点包括
- 尽量选取满足需求但较小的基础系统镜像,例如大部分时候可以选择debian:wheezy 或 debian:jessie 镜像,仅有不足百兆大小;
- 清理编译生成文件、安装包的缓存等临时文件;
- 安装各个软件时候要指定准确的版本号,并避免引入不需要的依赖;
- 从安全角度考虑,应用要尽量使用系统的库和依赖;
- 如果安装应用时候需要配置一些特殊的环境变量,在安装后要还原不需要保持的变量值;
- 使用 Dockerfile 创建镜像时候要添加 .dockerignore 文件或使用干净的工作目录。
b.非root用户下使用docker
docker几乎所有操作都需要root权限,但是每次sudo不可能.所以采用官方提供的把普通用户添加到docker用户组得方法.
1 | sudo groupadd docker #如果已经存在就不需要这一步了,17版默认安装好像自带了 |
d.gogs配置端口后运行的问题
在config文件–>需要添加Port xxxx`端口配置。E.g
1 | This config file is used for multi Git SSH Server. |
测试的时候不能直接测试ip,用别名e.g
1 | ssh -T git@gogs |
遗留的问题:
不能直接使用端口:ip下载,提示permission denied.Why? 之前曾经可以
1
2
3
4
5
6
7git clone ssh://git@139.199.xx.xx:100xx/jin/gogTest.git
Cloning into 'gogTest'...
Permission denied (publickey,keyboard-interactive).
fatal: Could not read from remote repository.
Please make sure you have the correct access rights
and the repository exists.如何使用多个不同的公私钥进行匹配.比如我服务器网站添加了两个公钥,然后本地也有两个不同名字的私钥,如何选择切换?
e.Win下安装docker
虽然不推荐在mac/win下通过跑linux虚拟机的方法再去跑docker,但是由于实际项目的确有winserver的历史遗留,也就一并试试吧… 系统支持待验证
主要是利用boot2docker:(可以想成一个简单的虚拟机,github提供exe下载) 其中带有以下组件:
- boot2docker Linux_ISO\
- virtualBox
- MSYS-git
- managementTool
安装完成运行了一个shell,就能直接运行docker的命令了,其他大致类似,建议选择新版winserver2016(内置支持)
5.后续计划
Docker的镜像放在公有的地方是可以,但是显然不是很好的办法,因为项目的私有问题.
加上同步的速度问题,最好的办法就是从内网去传输同步.配合gitLab/gogs这样.
打算自己建一个gogs到时候关联一下Docker,这样就能解决很多问题了.(已经非常简单的实现了)
补:Microsoft 2016server 已经开始内置了Docker的服务,从而进一步加强对docker的支持
甚至能在docker下直接跑一个windowsOS起来.不过只是初步的
附:参考pdf资料
- 去哪儿网docker构建.pdf
- 华为CCE_Docker容器实践.pdf
- docker简介
