docker 简明教程
本教程前一段的vagrant 是对于windows 或mac 平台的,因为docker 是基于linux的,如果没有linux系统环境,推荐使用vagrant来建立一个虚拟机,官方提供一个可以直接从操作docker的linux镜像,我觉得docker 和vagrant 有很多像的地方,可以多了解docker,有linux环境的直接看docker部分即可。像了解vagrant的同学,移步-》》vagrant中文文档
已有linux环境跳过vagrant,直接进去docker部分-》》go
Docker已经迅速发展了一段时间,不少同学可能都在对Docker的应用,实际的应用,解决开发和运营中的实际问题,如何应用Docker,对docker能做什么有了更多的需求,为此,我整理了一份 Docker应用教程 ,致力提供更多的 Docker应用案例和问题解决。初学的同学还请有先按本文了解docker的基本操作。
Docker 是个容器,像个碗或者盆,其实更像个橱柜 带格子的那种.
你可以把喜欢的东西放在各种各种的格子里,然后不管橱柜搬到哪,就你在里面放置的好玩意不会变。
这样你就可以轻松的在ubuntu上运行一个centos
下面是老外做的一个不是很直观也能看明白的直观图,对比docker和VM的不同:
这里有镜像可以下载 these slides 都是Docker提供的(不足最近github的访问速度是真xxx,随意最好找找有没有代理加快下载,如果对docker不了解,还是要谨慎一些,二次发布的镜像,也许会有问题).
获取docker
docker对mac支持不是很好,可以用boot2docker来解决.老外推荐使用CoreOs来操作Vagrant(这又是一个神器,将来会陆续在我的网站出现,请持续关注)
老外在这里强烈推荐CoreOS,说怎么怎么好,我还是推荐先使用ubuntu或者在windows上装个vbox在用ubuntu,coreos作为一个新型的服务器级别的系统,也十分值得关注,因为CoreOs将作为主力的docker容器发展。
下面这一段是老外将他在CoreOS安装docker的事,主要是 Vagrantfile
(这是一个Vagrant可以识别的配置文件):
如果使用NFS 就加下面一段:
如果使用vmware不使用virtualbox:
最好要加上一个插件:
如果你不使用CoreOS而是使用其他的,可以在这个页面 this page 找到安装方式(这个是官方的,这里是民间的http://www.simapple.com/255.html,陆续完善中). Note: Docker是基于 Ubuntu开发的随意选择什么,你懂得 .
如果在CoreOS上操作过程中,提示重启,请不要担心,这是为了启用特性所做的操作
下面为docker正式内容
你的第一个容器
第一步尝试是必须的,虽然你可能不是直接发现docker的强大,但是足以“管中窥豹”(这老外比我都罗嗦)
docker有一些基础的容器,也接受民间提供制作好的容器,以后你如果想贡献,也可以在这里 index.docker.io 发布自己的容器.
最流行最基础的Docker镜像还是“Ubuntu”
如果没有这个镜像,那么需要下载~
Run Bash:
什么事情都没有发生! 哈哈, 实际上已经有东西运行了. 运行
docker ps
(像在linux主机上运行
ps
) - 你什么容器也看不到,一个进程都没有(这老外~尼玛). Run
docker ps -a
, 见证奇迹的时刻!
我们已经可以看到一个在运行的
/bin/bash
, 但是没有任何进程在维持它的执行.一个docker容器是伴随进程运行的.
先记住上面说的. 让我们继续操作docker,来玩一会儿:
现在你可以看到你已经以root的身份登录到了docker 容器!
这些命令都在做什么?
- 运行一个容器 docker run
-t
- 分配一个(伪) tty-i
- 开发输入(so we can interact with it)ubuntu
- 使用ubuntu基础镜像/bin/bash
- 运行bash shell
跟进改变
使用 (ctrl+d
or type exit
) 来退出然后继续执行 docker ps -a
. :
复制粘贴现在运行的容器 ID (30557c9017ec
in my case). 运行
docker diff <container id>
我们可以看到我们仅仅登录了 bash之后的改变,创建了 .bash_history
file, a /dev
directory and a/dev/kmsg
file. 这是细微的变化,确实伟大的存在! Docker 会跟踪我们在容器中的所有改动. 事实上,docker就是运行我们创造改动,提交改动,发布改动,然后将改变带到任何地方. 这就是我们使用docker所依赖的基础.
下面我们就来安装点新玩意到容器中,让把它们打包成我们自己的.
等这些都运行完了之后,退出,再执行
docker ps -a
. 在复制最新的ID
docker diff <Container ID>
当然又有很多的新文件被添加. 下面我们就来打包我们的版本,为了以后更好的使用.我们将提交修改,给它命名并打上标签。 我们将使用:
docker commit <Container ID> <Name>:<Tag>
我们来看看我们打包好的镜像. Run
docker images
你已经注意到了那么多的ubuntu啊. 当我第一次加载使用ubuntu基础镜像的时候,就已经加载相应的ubuntu标记,更多知识请浏览 Docker index.
非常有趣,不管怎样我们已经用了自己的镜像 叫做
fideloper/docker-example
并且有个版本标签
0.1
!
使用 Dockerfile 建立一个服务器
让我们使用Dockerfile来创建一个服务器,大概就是通过一个配置文件,让git和wget自动的完成这个服务器环境的搭建工作.
创建一个目录,然后cd进去,因为我们要使用nginx服务器,就需要有个默认的配置文件.
创建一个叫做 default
的配置文件:
这就是nginx的基础配置了.
下面我们创建一个 Dockerfile
并添加如下内容, 修改镜像FROM为我们自己的镜像(多么happy):
这些东西有都是什么的?
FROM
告诉docker使用哪个镜像,用什么版本RUN
以root用户身份来执行linux命令ADD
复制文件到容器内这是一个非常方便来管理配置文件的方式
EXPOSE
暴露端口给主机,也可以添加更多的端口比如:EXPOSE 80 443 8888
CMD
执行一个命令 (但不是以sh -c
). 这通常是来运行长时间的进程,但是我们只是来启动nginx.在生产环境中,我们想看到nginx在运行失败的情况下的表现
保存好这些,让我们来build一个新镜像
如果它正常工作了并结束
Successfully built 88ff0cf87aba
(这个容器ID并不一定都是一样的).
检查一下你有获得的什么镜像 docker images
:
再运行一下 docker ps -a
:
你可以看到 每一行Dockerfile中的指令, 一个新的容器已经诞生 if that line results in a change to the image used. Similar(ish) to version control! (Also, how funny is the name "backstabbing_turing"?)(这一段很难明白?难道又是老外在用,英语文化开玩笑,希望给个指点)
最后,执行这个web服务
让我们来运行web服务器! 使用
docker run -p 80:80 -d nginx-example
(确定你要使用的名称).
-p 80:80 经容器的80端口 绑定到了主机上 通过curl localhost 或者访问主机ip就可以看到运行的状态
现在我们使用 docker ps
而不是 docker ps -a
- 我们可以看到容器中正在运行的进程(回想最初的命令). 执行 curl localhost
:
我们看到了nginx的回应,但是是500错误. 这是因为我们并没有一个index.html
资源文件让nginx返回. 让我们停止这个容器的运行 docker stop <container id>
:
来解决一下这个问题,我们来共享一个目录在主机和容器之间,这样就用个index.html了,首先创建一个index.html在我们想要贡献的目录中
然后我们再启动这个容器(注意命令):
docker run
- 启动容器-v /path/to/host/dir:/path/to/container/dir:rw
- 指定一个目录共享到容器,并且指定权限为读写,也可以指定为只读-p 80:80
- 绑定端口.-d nginx-example
启动nginx-example的容器,由于在配置文件的CMD中已经指定启动了
nginx ,在容器启动时nginx即启动
运行 curl localhost
:
...或者直接访问主机ip
注意这个ip是主机的ip. 我已经在 Vagrantfile
中指定了ip。我不需要知道要转发的ip究竟是什么? 当时可以通过这个命令来看到
docker inspect <Container ID>
链接不同的容器
现在已经可以将多个容器联合在一起了 。能将容器联合在一起,是一项非常重要的技能. 举个例子, 比如你的web容器想要链接你的数据库容器. 链接可以让多个分支应用,独立于你的应用。
举个例子:
启动一个容器,并且取个有意义点的名字 (在这里就叫, mysql
):
启动你的web容器 将它和另外一个容器链接在一起 -d name:db
(where db
is an arbitrary name used in the container's environment variables):
在例子中,
some-application-image
有这样的环境变量设置
DB_PORT_3306_TCP_ADDR=172.17.0.8
and
DB_PORT_3306_TCP_PORT=3306
用于在应用中的设置
这是一个mysql的dockerfile MySQL Dockerfile
结论
我们就是可以这么简单的来创建一台服务器,添加应用代码,控制应用。执行环境中的每一件事都在你的掌控之中
通过这种方式,我们可以 跳过复杂的环境设置,专心于自己的代码.
P.S. - Tips and Tricks
如果执行完了这次体验,你想自己做点什么,并且清理掉之前的docker 容器:
删除容器:
docker rm <Container ID>删除所有容器:
docker rm $(docker ps -a -q)移除镜像:
docker rmi <Container ID>移除所有镜像:
docker rmi $(docker ps -a -q)
Note: 在移除镜像前,你必须删除掉,所有依赖于该镜像的容器
加入你已经完整体验了上面的教程,那么就已经对docker有了很系统的了解,因为docker 无非就是用来构建一个可移植环境,为了能有进一步的提高,推荐进行下面的学习:
docker操作命令,主要熟悉一个常用的操作,docker的命令不多,基本上都会用到,推荐:docker命令详解
Dockerfile的编写,用于建立一个属于自己的定制化的docker image镜像,docker建立镜像很简单,主要是要能够编写Dockerfile进行定制,推荐:Dockerfile说明文档