背景
为什么使用docker
1.为了实现开发、测试、生产环境的一致性,项目更快的交付与部署。
2.即启即用,易创建、扩展和销毁,对于服务器的部署尝试极其方便。
为什么不使用虚拟机(vbox),跟docker区别在哪里
1.器和虚拟机仅仅相似于它们都提供了隔离环境。从简单开发使用的角度来说,docker比vbox之类搭建的虚拟机(centos)更方便快捷。
2.但在简单使用后还是需要深入理解他们之间的区别:vm与docker框架,直观上来讲vm多了一层guest OS,同时Hypervisor会对硬件资源进行虚拟化,docker直接使用硬件资源,所以资源利用率相对docker低也是比较容易理解的。
基本概念
1.镜像 一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数
2.容器 镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的类和实例一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。
3.仓库 镜像构建完成后,可以很容易的在当前宿主上运行,但是,如果需要在其它服务器上使用这个镜像,我们就需要一个集中的存储、分发镜像的服务 1)docker hub 2)私有仓库
4.Dockerfile 镜像的定制实际上就是定制每一层所添加的配置、文件。如果我们可以把每一层修改、安装、构建、操作的命令都写入一个脚本,用这个脚本来构建、定制镜像,那么之前提及的无法重复的问题、镜像构建透明性的问题、体积的问题就都会解决。其内包含了一条条的指令(Instruction),每一条指令构建一层,因此每一条指令的内容,就是描述该层应当如何构建。
5.数据卷 一个可供一个或多个容器使用的特殊目录,它绕过 UFS,可以提供很多有用的特性:
数据卷可以在容器之间共享和重用
对数据卷的修改会立马生效
对数据卷的更新,不会影响镜像
数据卷默认会一直存在,即使容器被删除
使用镜像
1. 获取镜像
docker pull [选项] [Docker Registry地址]<仓库名>:<标签>
docker pull ubuntu:14.04
2.列出镜像 docker images
3.镜像体积 docker images列表中的镜像体积总和并非是所有镜像实际硬盘消耗。由于 Docker 镜像是多层存储结构,并且可以继承、复用,因此不同镜像可能会因为使用相同的基础镜像,从而拥有共同的层。由于 Docker 使用 Union FS,相同的层只需要保存一份即可,因此实际镜像硬盘占用空间很可能要比这个列表镜像大小的总和要小的多。
4.删除虚悬镜像 docker rmi $(docker images -qf dangling=true)
容器
1.启动
docker run -it --rm ubuntu:14.04 /bin/bash
-it:这是两个参数,一个是-i:交互式操作,一个是-t终端。我们这里打算进入bash执行一些命令并查看返回结果,因此我们需要交互式终端。
--rm:这个参数是说容器退出后随之将其删除。默认情况下,为了排障需求,退出的容器并不会立即删除,除非手动docker rm。我们这里只是随便执行个命令,看看结果,不需要排障和保留结果,因此使用--rm可以避免浪费空间。
所以本条命令会启动ubuntu14.04镜像(若不存在则先拉取)并进入容器内,当在容器内退出后,我们可以docker ps -a看到此容器将被销毁了。
2.进入容器 docker exec -it ${container id} /bin/bash
3.删除容器 docker rm ${container id}
4.在容器内运行一个后台守护进程.
docker run -d ubuntu:14.04 /bin/sh -c "while true; do echo hello world; sleep 1; done"
会返回一串容器id,通过docker logs ${container id}可以看到有一列hello world.
本例中,我们通过-d属性,让容器运行在后台. 由于有了循环echo,容器保持着开启状态,如果没有这个echo,容器启动当即退出。 因为这一个进程已完成了他的工作。 所以当我们想创建如nginx需要持续工作的服务时,要在容器内作一个如死循环的指令,让容器保持开启。 通常我们会在里面这么干: tail -f /dev/null
数据管理
1.数据卷 一个可供一个或多个容器使用的特殊目录,它绕过 UFS,可以提供很多有用的特性:
数据卷可以在容器之间共享和重用
对数据卷的修改会立马生效
对数据卷的更新,不会影响镜像
数据卷默认会一直存在,即使容器被删除
即使镜像被删除,数据卷也仍然会持久化到本地。
将宿主目录挂载为数据卷,通过 -v 标示你可以挂载一个宿主目录到容器中。
docker run -d -P --name web -v /src/webapp:/opt/webapp training/webapp python app.py
PS:在使用挂载时,很容易出现一个问题,暂停其他容器后,数据卷没清空。在下一次容器再启动时,又会生成新的数据卷,久而久之,就会占满空间。 所以我们需要时不时清理数据卷.
docker volume rm $(docker volume ls -qf dangling=true)
具体对数据卷的分析可参考: https://www.goodmemory.cc/docker%E5%AE%B9%E5%99%A8%E7%9A%84%E6%95%B0%E6%8D%AE%E7%AE%A1%E7%90%86/
仓库
Docker Registry 是一个用来管理Docker镜像的服务,本身也是一个Docker容器。大部分情况下都可以使用Docker Hub,私有的Docker Registry使用场景主要在当需要对容器镜像存储进行完全控制或需要把镜像管理进行集成的情况。
初次搭建:
docker run -d -p 5000:5000 -v `pwd`/data:/var/lib/registry --restart=always --name registry registry:2.1.1
我们在本地给hello-world:latest这个镜像打一个tag,并尝试将新tag下的image push到Registry中去:
docker tag hello-world:latest 192.168.99.100:5003/hello-world:0.1,此时docker images将会看到一个0.1版本的hello-world镜像
docker push 192.168.99.100:5003/hello-world 推送镜像
可在此地址看到上传的http://${docker ip}/v2/_catalog?n=1000
docker pull 192.168.99.100:5003/hello-world 拉取镜像
关于仓库还可以做很多事情,安全等。 具体可参考:http://tonybai.com/2016/02/26/deploy-a-private-docker-registry/
编排
在实际运用中,我们会采用容器编排套件来运行容器,而不是类似docker run的形式。 这里我们用的是compose,其定位是 “定义和运行多个 Docker 容器的应用。
解决方案
这边会给出基于lnmp服务安装的实例(各环境的docker搭建及demo看这里). 为了便于管理各服务,我们使用docker-compose编排服务。
服务搭建配置: https://github.com/lilclimate/Docker-Webservice,具体实现可以看github,下面会挑重点讲。
第一步,把lnmp拆开。build一个centos6的镜像,基于这个镜像分别建立openresty(nginx)作为server和nginx proxy两个镜像。再基于openresty镜像的层面建立php。 mysql使用官方的镜像独立安装一个。 现在我们就拥有了openresty-php和mysql组成拥有简单的负载均衡的lnmp环境了。
第二步,添加配置和代码。在挂载的data/etc/nginx下添加vhosts/ci-demo.conf和vhosts_proxy/ci-demo.conf用于server和负载均衡配置。 大致如下:
第三步,docker-compose up& 启动。
网友评论