Docker是一个基于轻量级虚拟化技术的容器,整个项目基于Go语言开发,并采用了Apache 2.0协议。Docker能够将咱们的应用程序打包封装到一个容器中,该容器包含了应用程序的代码、运行环境、依赖库、配置文件等必需的资源,经过容器就能够实现方便快速而且与平台解耦的自动化部署方式,不管你部署时的环境如何,容器中的应用程序都会运行在同一种环境下。python
举个栗子,小明写了一个CMS系统,该系统的技术栈很是广,须要依赖于各类开源库和中间件。若是按照纯手动的部署方式,小明须要安装各类开源软件,还须要写好每一个开源软件的配置文件。若是只是部署一次,这点时间开销仍是能够接受的,但若是小明每隔几天就须要换个服务器去部署他的程序,那么这些繁琐的重复工做无疑是会使人发狂的。这时候,Docker的用处就派上场了,小明只须要根据应用程序的部署步骤编写一份Dockerfile文件(将安装、配置等操做交由Docker自动化处理),而后构建并发布他的镜像,这样,无论在什么机器上,小明都只须要拉取他须要的镜像,而后就能够直接部署运行了,这正是Docker的魅力所在。git
那么镜像又是什么呢?镜像是Docker中的一个重要概念:github
Image(镜像):它相似于虚拟机中使用到的镜像,因为任何应用程序都须要有它本身的运行环境,Image就是用来提供所需运行环境的一个模板。redis
Container(容器):Container是Docker提供的一个抽象层,它就像一个轻量级的沙盒,其中包含了一个极简的Linux系统环境与运行在其中的应用程序。Container是Image的运行实例(Image自己是只读的,Container启动时,Docker会在Image的上层建立一个可写层,任何在Container中的修改都不会影响到Image,若是想要在Image保存Container中的修改,Docker采用了基于Container生成新的Image层的策略),Docker引擎利用Container来操做并隔离每一个应用(也就是说,每一个容器中的应用都是互相独立的)。docker
其实从Docker与Container的英文单词原意中就能够体会出Docker的思想。Container能够释义为集装箱,集装箱是一个能够便于机械设备装卸的封装货物的通用标准规格,它的发明简化了物流运输的机械化过程,使其创建起了一套标准化的物流运输体系。而Docker的意思为码头工人,能够认为,Docker就像是在码头上辛勤工做的工人,把应用打包成一个个具备某种标准化规格的"集装箱"(其实这里指出的集装箱对应的是Image,在Docker中Container更像是一个运行中的沙盒),当货物运输到目的地后,码头工人们(Docker)就能够把集装箱拆开取出其中的货物(基于Image来建立Container并运行)。这种标准化与隔离性能够很方便地组合使用多个Image来构建你的应用环境(Docker也提倡每一个Image都遵循单一职责原则,也就是只作好一件事),或者与其余人共享你的Image。shell
本文做者为SylvanasSun(sylvanas.sun@gmail.com),首发于SylvanasSun’s Blog。
原文连接:sylvanassun.github.io/2017/11/19/…
(转载请务必保留本段声明,而且保留超连接。)bash
在上文中咱们提到了Docker是基于轻量级虚拟化技术的,因此它与咱们日常使用的虚拟机是不同的。虚拟机技术能够分红如下两类:服务器
系统虚拟机:经过软件对计算机系统的模拟来提供一个真实计算机的替代品。它是物理硬件的抽象并提供了运行完整操做系统所需的功能。虚拟机经过物理机器来管理和共享硬件,这样实现了多个虚拟机环境彼此之间的隔离,一台机器上能够运行多个虚拟机,每一个虚拟机包括一个操做系统的完整副本。在系统虚拟机中,所运行的全部软件或操做都只会影响到该虚拟机的环境。咱们常用的VMWare就是系统虚拟机的实现。并发
程序虚拟机:容许程序独立运行在平台以外。比较典型的例子就是JVM,Java经过JVM这一抽象层使得Java程序与操做系统和硬件平台解耦(由于每一个Java程序都是运行在JVM中的),所以实现了所谓的compile once, run everywhere。app
Docker所用到的技术与上述两种都不相同,它使用了更轻量级的虚拟化技术,多个Container共享了同一个操做系统内核,而且就像运行在本地上同样。Container技术相对于虚拟机来讲,只是一个应用程序层的抽象,它将代码与依赖关系打包到一块儿,多个Container能够在同一台机器上运行(意味着一个虚拟机上也能够运行多个Container),并与其它Container共享操做系统内核,每个Container都在用户空间中做为一个独立的进程运行,这些特性都证实了Container要比虚拟机更加灵活与轻量(通常都是结合虚拟机与Docker一块儿使用)。
Container技术其实并非个新鲜事物,最先能够追溯到UNIX中的chroot(在1979年的V7 Unix中引入),它能够改变当前正在运行的进程及其子目录的根目录,在这种修改过的环境下运行的程序不能在指定的目录树以外访问文件,从而限制用户的活动范围,为进程提供了隔离空间。
以后各类Unix版本涌现出不少Container技术,在2006年,Google提出了"Process Containers"指望在Linux内核中实现进程资源隔离的相关特性,因为Container在Linux内核中的定义过于宽泛混乱,后来该项目更名为CGroups(Control Groups),实现了对进程的资源限制。
2008年,LXC(Linux Containers)发布,它是一种在操做系统层级上的虚拟化方法,用于在Linux系统上经过共享一个内核来运行多个互相隔离的程序(Container)。LXC正是结合了Linux内核中的CGroups和对分离的名称空间的支持来为应用程序提供了一个隔离的环境。而Docker也是基于LXC实现的(Docker的前身是dotClound公司中的内部项目,它是一家提供PaaS服务的公司。),并做出了许多改进。
在使用Docker以前你须要先安装Docker(这好像是一句废话。。。),根据不一样的平台安装方法都不相同,能够去参考Install Docker | Docker Documentation或者自行Google。
安装完毕以后,输入docker --version
来确认是否安装成功。
$ docker --version
Docker version 17.05.0-ce-rc1, build 2878a85复制代码
从Docker Hub中能够pull到其余人发布的Image,咱们也能够注册一个帐号去发布本身的Image与他人共享。
[root@Jack ~]# docker search redis # 查看redis镜像是否存在
[root@Jack ~]# docker pull redis # 拉取redis镜像到本机
Using default tag: latest
Trying to pull repository docker.io/library/redis ...
latest: Pulling from docker.io/library/redis
Digest: sha256:cd277716dbff2c0211c8366687d275d2b53112fecbf9d6c86e9853edb0900956
[root@Jack ~]# docker images # 查看镜像信息
REPOSITORY TAG IMAGE ID CREATED SIZE
docker.io/python 3.6-onbuild 7195f9298ffb 2 weeks ago 691.1 MB
docker.io/mongo latest d22888af0ce0 2 weeks ago 360.9 MB
docker.io/redis latest 8f2e175b3bd1 2 weeks ago 106.6 MB复制代码
有了Image,以后就能够在其之上运行一个Container了,命令以下。
[root@Jack ~]# docker run -d -p 6379:6379 redis # 运行redis,-p表明将本机上6379端口映射到Container的6379端口 -d表明在后台启动
[root@Jack ~]# docker ps -a # 查看容器信息,若是不加-a只会显示当前运行中的容器
# 若是想要进入容器中,那么须要执行如下命令
[root@Jack ~]# docker ps # 先得到容器的id
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
1f928073b7eb redis "docker-entrypoint.sh" 45 seconds ago Up 44 seconds 0.0.0.0:6379->6379/tcp desperate_khorana
[root@Jack ~]# docker exec -it 1f928073b7eb /bin/bash # 而后再执行该命令进入到容器中
root@1f928073b7eb:/data# touch hello_docker.txt # 在容器中建立一个文件
root@1f928073b7eb:/data# exit # 退出
exit
[root@Jack ~]#
# 也能够在启动时直接进入 命令以下
[root@Jack ~]# docker run -d -it -p 6379:6379 redis /bin/bash复制代码
咱们对Container作出了修改,若是想要保留这个修改,能够经过commit命令来生成一个新的Image。
# -m为描述信息 -a为做者 1f9是你要保存的容器id 取前3个字符 docker能够自行识别
# sylvanassun/redis为镜像名 :test 为一个tag 通常用于标识版本
[root@Jack ~]# docker commit -m "test" -a "SylvanasSun" 1f9 sylvanassun/redis:test
sha256:e7073e8e5bd70b8d58092fd6bd8c2551e65dd29241c235eddf2a7f4b4b25cbbd
[root@Jack ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
sylvanassun/redis test e7073e8e5bd7 2 seconds ago 106.6 MB
docker.io/python 3.6-onbuild 7195f9298ffb 2 weeks ago 691.1 MB
docker.io/mongo latest d22888af0ce0 2 weeks ago 360.9 MB
docker.io/redis latest 8f2e175b3bd1 2 weeks ago 106.6 MB复制代码
想删除一个容器或镜像也很简单,但在删除镜像前须要先删除依赖于它的容器。
[root@Jack ~]# docker stop 1f9 # 关闭运行中的容器,相应的也有docker start id命令来启动一个容器
1f9
[root@Jack ~]# docker rm 1f9 # 删除容器
1f9
[root@Jack ~]# docker rmi e70 # 删除上面保存的镜像
Untagged: sylvanassun/redis:test
Deleted: sha256:e7073e8e5bd70b8d58092fd6bd8c2551e65dd29241c235eddf2a7f4b4b25cbbd
Deleted: sha256:751db4a870e5f703082b31c1614a19c86e0c967334a61f5d22b2511072aef56d复制代码
若是想要本身构建一个镜像,那么须要编写Dockerfile文件,该文件描述了镜像的依赖环境以及如何配置你的应用环境。
# 使用python:2.7-slim 做为父镜像
FROM python:2.7-slim
# 跳转到/app 其实就是cd命令
WORKDIR /app
# 将当前目录的内容(.)复制到镜像的/app目录下
ADD . /app
# RUN表明运行的shell命令,下面这条命令是根据requirements.txt安装python应用的依赖包
RUN pip install --trusted-host pypi.python.org -r requirements.txt
# 暴露80端口让外界访问
EXPOSE 80
# 定义环境变量
ENV NAME World
# 当容器启动时执行的命令,它与RUN不一样,只在容器启动时执行一次
CMD ["python", "app.py"]复制代码
而后就能够经过docker build -t xxx/xxxx .
命令来构建镜像,-t
后面是镜像名与tag等信息,注意.
表示在当前目录下寻找Dockerfile文件。
学会如何构建本身的镜像以后,你是否也想将它发布到Docker Hub上与他人分享呢?要想作到这一点,须要先注册一个Docker Hub帐号,以后经过docker login
命令登陆,而后再docker push image name
,就像在使用Git同样简单。
关于Docker的更多命令与使用方法,请参考Docker Documentation | Docker Documentation,另外我还推荐使用Docker Compose来构建镜像,它能够很方便地组合管理多个镜像。
Docker提供了很是强大的自动化部署方式与灵活性,对多个应用程序之间作到了解耦,提供了开发上的敏捷性、可控性以及可移植性。同时,Docker也在不断地帮助愈来愈多的企业实现了向云端迁移、向微服务转型以及向DevOps模式的实践。
现在,微服务与DevOps火爆程度日益渐高,你又有何理由选择拒绝Docker呢?让咱们一块儿选择拥抱Docker,拥抱将来!