├── .gitignore ├── README.md ├── docker-0-7-0-major-features.md ├── docker-15-tips.md ├── docker-closes-15-m-dollars-series-b-foundings.md ├── docker-http-proxy-with-golang-en.md ├── docker-http-proxy-with-golang.md ├── docker-segmentfault-qa-sub-site.md ├── fiona.md ├── fish-shell-docker-completion-mac-os.md ├── how-to-deploy-your-own-private-docker-registry.md ├── lance.md ├── meaglith.md ├── quickly-ssh-into-a-docker-container.md ├── rocker.md └── the-docker-book-sample-download.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 2 | *.o 3 | *.a 4 | *.so 5 | 6 | # Folders 7 | _obj 8 | _test 9 | 10 | # Architecture specific extensions/prefixes 11 | *.[568vq] 12 | [568vq].out 13 | 14 | *.cgo1.go 15 | *.cgo2.c 16 | _cgo_defun.c 17 | _cgo_gotypes.go 18 | _cgo_export.* 19 | 20 | _testmain.go 21 | 22 | *.exe 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Dockboard Docs 2 | ======== 3 | 4 | The backup of dockboard.org contents. 5 | -------------------------------------------------------------------------------- /docker-0-7-0-major-features.md: -------------------------------------------------------------------------------- 1 | ![Why named docker?](http://docker.u.qiniudn.com/PPT_why_named_docker.jpg) 2 | 3 | 嗨,Docker 0.7 终于和各位见面了!希望大家喜欢。自 0.6.0 发布以来,经过无数的 bug 修复和使用细节的改进,新版本增加了 7 个主要功能: 4 | 5 | - 功能1:标准 Linux 支持 6 | - 功能2:存储驱动 7 | - 功能3:离线传输 8 | - 功能4:链接 9 | - 功能5:容器命名 10 | - 功能6:高级端口跳转 11 | - 功能7:更高的软件质量 12 | 13 | 您可以在 [Git库更新日志](https://github.com/dotcloud/docker/blob/v0.7.0/CHANGELOG.md) 查看详情,也可以查看下文来了解各个新功能的详情。 14 | 15 | ###致谢! 16 | 17 | 130 名杰出的朋友参加了 Docker 的发布!部分人士列举如下: 18 | 19 | Alex Larsson、Josh Poimboeuf、Lokesh Mandvekar、Vincent Batts、Adam Miller、Marek Goldmann and Matthew Miller from the Red Hat team、 Fred Kautz、Tianon “andrew” Gravi、Paul Nasrat、Sven Dowideit、James Turnbull、Edmund Wagner、David Calavera、Travis Cline、Gurjeet Singh、Justin Force、Johan Euphrosine、Jerome Petazzoni、Ole Reifschneider、Andy Rothfusz、Will Rouesnel、Greg Thornton、Scott Bessler、Todd Lunter、Vladimir Rutsky、Nicolas Dudebout、Jim Alateras、Roger Peppe 20 | 21 | 向以上各位,以及所有对 Docker 的发布伸出援助之手的人们致以谢意:谢谢你们! 22 | 23 | ###功能1:标准 Linux 支持 24 | 25 | _0.7.0 版引入该功能,为此特别感谢 aufs 的作者们:Alex Larsson、(Red Hat 团队)、Junjiro R. Okajima。_ 26 | 27 | 0.7.0 版引入了几个主要的新功能,其中最受期待的无疑是对标准 Linux 的支持。如今,使用 Docker 已经不再需要向 Linux 内核打补丁,感谢 Alex Larsson 为我们贡献了一个新的存储驱动(请参考下一个功能“存储驱动”)。这意味着 Docker 将会跳出内核限制,运行于所有主流 Linux 发行版中,包括 Fedora、RHEL、Ubuntu、Debian、Suse、 Gentoo、Arch 等)。[猛击此处](http://docs.docker.io/en/latest/installation/) 来查看你最喜爱的 Linux 发行版的 Docker 安装文档。 28 | 29 | 30 | ###功能2:存储驱动 31 | 32 | _0.7.0 版本引入_ 33 | 34 | Docker 的一个核心功能是瞬间建出很多底层文件系统一致的 Docker 容器。Docker 在底层大量使用 AUFS(由 Junjiro R. Okajima 编写)作为 copy-on-write 的存储机制。AUFS 是一款超赞的软件,已经在过去的几年中安全地拷贝了无数个容器,其中相当大一部分用于生产环境。但非常可惜的是,AUFS 一直不是 Linux 标准内核的一部分,我们也不知道何时它才会加入到 Linux 标准内核中。 35 | 36 | Docker 0.7 通过引入一个存储驱动 API 来处理不同驱动的传输,解决了这个问题。通过与 Alex Larsson 和出色的 Red Hat 团队合作,使用高度灵活的 LVM 快照技术实现了 copy-on-write,现在支持三种驱动:AUFS、VFS(使用简单目录和拷贝)和 DEVICEMAPPER 。实验性的 BERFS 驱动目前正在开发中,ZFS、Gluster、Ceph 也将推出。 37 | 38 | 39 | Docker 的后台程序在启动时会根据情况自动选择一种合适的驱动。如果系统支持 AUFS,Docker 会自动选择 AUFS,升级后所有的容器和镜像都是可用的;如果系统不支持 AUFS,Docker 将使用 devicemapper 作为默认的驱动。同一台机器中的驱动之间不能共享数据,但驱动产生的镜像可以互相兼容,同时也兼容之前任何版本的 Docker。这意味着 [列表](http://index.docker.io) 中的所有镜像(包括 [此处](http://blog.docker.io/2013/11/introducing-trusted-builds/) 列出的受信任镜像),在任何已安装的 Docker 中都可以使用。 40 | 41 | ###功能3:离线传输 42 | 43 | _0.6.7 版中引入,特别感谢:Frederic Kautz_ 44 | 45 | **离线传输**可以把容器镜像导出到本地的一个独立文件包,该文件包可以加载到任何其他的 Docker 后台中。加载后的镜像 100% 保留了原始镜像的所有内容,包括配置、创建日期以及构建日志等等。导出的文件就是一个普通的文件夹,可以用任何传输方式进行传输,例如 ftp 、磁盘、安装文件等等。 46 | 47 | 离线传输功能对于软件供应商特别有用,通常他们需要把软件做成封装好的软件包发给“企业级”用户。现在,通过 Docker 的离线传输,供应商可以把更新后的软件放入 Docker 容器再发给用户,既不影响软件发行机制,用户也不必担心安全问题。 48 | 49 | 正如 Github 企业版团队的 David Calavera 所说:“有了离线传输,用 Docker 容器构建内部部署[^1]的软件产品变得非常容易。无需注册,你的容器就可以部署到任何地方。” 50 | 51 | ###功能4:高级端口重定向 52 | 53 | _0.6.5版中引入_ 54 | 55 | _注意:这项功能使安全性获得了两个突破性的小改进。本节最后有详细说明。_ 56 | 57 | 新版Docker扩展了 `run` 命令的 `-p` 参数,用户可以更灵活的控制端口重定向。老版本中,主机上的所有网卡都只能自动重定向,新版中,用户可以自行指定要重定向的网卡。使用现有的命令就可以使用新的重定向功能。 58 | 59 | 例如: 60 | 61 | - `p 8080` 把主机上的所有动态端口重定向到容器的 80 端口。 62 | - `p 8080:8080` 把主机上所有以 8080 为静态端口的服务重定向到容器的8080端口。 63 | - `p 127.0.0.1:80:80` 把主机上所有 localhost 的静态 80 端口的服务重定向到容器的 80 端口。 64 | 65 | 您也可以禁止主机上所有网卡的重定向,来有效的阻止外部对端口的访问。结合“链接”(请参见后面的“链接”一节),端口重定向技术会很有用:假设您要绕过公共网络,把一个未被保护的数据库端口直接暴露给一个应用程序容器(而不把端口开放到公共网络),只需要增加一个 **_-expose_** 参数,而不必指定 Dockerfile 。 66 | 67 | 0.7.0 在安全方面有了两个突破性的改变: 68 | 69 | 首先,`docker run` 命令默认不再对主机进行端口重定向了。这样做可以提高安全性:端口默认是私有的,用户可以指定 `-p` 参数对外开放接口。如果您现在默认把端口暴露到所有网卡,请注意,这样在 0.6.5 之后就行不通了。如果您还想以前一样开放端口,请用 `-p` 参数指定端口的值。 70 | 71 | 其次,我们不再推荐 [EXPOSE文档](http://docs.docker.io/en/latest/use/builder/#expose) 中提到的高级“ `:` ”语法。这项特殊语法允许用户在 Dockerfile 中提前指定网卡端口的重定向。我们认为现这种方式提前限制了系统管理员对主机端口重定向的控制,不利于开发和运维理的隔离,因此这种方式不再推荐使用,而常规的“ `EXPOSE ` ”语法不受影响。 72 | 73 | 例如: 74 | 75 | - `EXPOSE 80` 暴露 tcp 的 80 端口,和老版本一样。 76 | 77 | - `EXPOSE 80:80` 不推荐使用,这种方式实际上等价于 `EXPOSE 80` ,将产生警告,指定的公共端口 80 将会被无情的忽略。 78 | 79 | 非常抱歉,我们不得不对 Docker 进行了这样的"突破性"的改动。我们尽量减小改动带来的不便,也希望大家看到,这些改进是值得的! 80 | 81 | ###功能5:链接 82 | 83 | _0.6.5 版引入_ 84 | 85 | 链接使容器能够安全的互相访问。要关闭容器间的互访,可以设置启动参数 `-icc=false` , icc 参数设置为 false 时, A 容器无法访问 B 容器,除非 B 容器通过链接的方式允许 A 的访问。这对容器的安全性有极大的好处。当两个容器连接在一起时,Docker 为两个容器创建一个父子关系。父容器可以通过名称、开放端口、ip 等环境参数来访问子容器的信息。 86 | 87 | 当 Docker 为两个容器创建链接时,会使用子容器暴露出来的端口为父容器创建一个安全的访问通道。如果一个数据库容器只暴露 8080 端口并关闭了容器间的互相通信,那么其连接的容器将只能访问 8080 端口。 88 | 89 | 例如: 90 | 91 | 当我们运行 WordPress 容器时,需要连接到数据库,如 MySQL 或 MariaDB 。使用链接,可以轻松访问后端数据库,无需修改 WordPress 站点的配置文件。 92 | 93 | 为了让 WordPress 容器可以访问不同的数据库,我们要用到别名,在本例中,我们用 ”**db**” 作为数据库的别名,这样,无论数据库容器叫什么名字,我们都可以通过一个统一的别名来访问数据库。使用下例中的两个数据库容器,我们可以将其和我们的 WordPress 容器连接起来。 94 | 95 | 要创建链接,只需在 `docker run` 命令中加入 `-link` 参数: 96 | 97 | - `docker run -d -link mariadb:db user/wordpress` 或者 98 | 99 | - `docker run -d -link mysql:db user/wordpress` 100 | 101 | 通过别名 db 链接到数据库容器后,我们可以查看 WordPress 容器的环境,并可以查看数据库的 ip 和端口。 102 | 103 | `$DB_PORT_3306_TCP_PORT` 104 | 105 | `$DB_PORT_3306_TCP_ADDR` 106 | 107 | `-link` 中指定的参数将作为环境变量的前缀。另外,我们推荐您阅读 Docker 文档中的例子《 [Building a redis container to link as a child of our web application](http://docs.docker.io/en/latest/use/working_with_links_names/#links-service-discovery-for-docker) 》。 108 | 109 | ###功能6:容器命名 110 | 111 | _0.6.5 版开始支持_ 112 | 113 | 很高兴宣布,我们终于可以关闭 [issue#1](https://github.com/dotcloud/docker/issues/1) 了!现在,为 `docker run` 指定 `-name` 参数,就可以给你的容器起一个有意义的、容易记住的名字了。如果没有指定名称,Docker 会自动为容器生成一个名称。要把一个容器和另一个容器连接起来,您需要提供子容器的名称和别名,格式如下: 114 | 115 | `-link child_name:alias` 116 | 117 | 多说无益,案例教学马上开始!你可以像下面这样,为两个数据库建立相应的别名,并用别名来运行对应的数据库。 118 | 119 | - `docker run -d -name mariadb user/mariadb` 120 | 121 | - `docker run -d -name mysql user/mysql` 122 | 123 | 然后,所有通过 id 访问容器的命令中,都可以用别名来代替 id 124 | 125 | - `docker restart mariadb` 126 | 127 | - `docker kill mysql` 128 | 129 | 130 | ###Quality功能7:软件质量 131 | 132 | _特别感谢:Tianon Gravi、 Andy Rothfusz 和 Sven Dowideit_ 133 | 134 | 应该说,“质量”不能算一个真正的功能,但是软件质量对我们来说太重要了!我们还是决定把“质量”加入到新功能列表中。0.7 版本中,我们特别关注了软件质量,并且在后续版本中,我们会更加注重软件品质。 135 | 136 | Docker 的活跃发展令人难以置信,而且在短时间内获得了巨大成功。但是像 Docker 这样活跃的项目,持续的跟进是很困难的。尽管 Docker 已多次改进,但很多代码依然不成熟,或者尚未完成、或者需要重构甚至重写。Docker 的发布就像打开一扇防洪闸门,尽管经历6个月、2844个 pull request 的演进,代码问题依旧淹没在每天无数贡献和功能需求的洪流中。 137 | 138 | 我们花了一些时间来忍受并最终适应 Docker 疯狂的发展速度;最终,我们找到了解决途径。从 0.7 版本开始,我们将把质量放在第一位,并从多方面面严格把关:用户界面、测试覆盖率、代码的健壮性、易开发性、文档以及 API 的前后连贯性。我们深知,对于 Docker 的那些 bug ,目前还没有银弹[^2]。我们最初规划了宏大的“代码重写”计划,但最终我们决定放慢速度,稳扎稳打,一步步处理问题。日复一日,不断提交、再提交,我们会让 Docker 逐步发展起来。 139 | 140 | 对于大家的支持,我们心怀感激。无数人看到了 Docker 的潜力,面对 bug 和缺陷,他们会说”还好啦“,“ Docker 很有用,我们不介意它还有点儿粗糙”。我们希望有一天,人们会说:“我用 Docker,因为它很有用。而且,非常可靠!” 141 | 142 | 那一天,不远了! 143 | 144 | 感谢所有人,感谢你们的支持! 145 | 146 | 向0.8进军! 147 | 148 | Solomon、 Michael、 Victor、 Guillaume 以及所有的 Docker 维护者们,加油! 149 | 150 | #####[^1] 原文为" on-premises software ",是指运行在用户自己的生产、营业场所的软件产品,区别于部署在远程的软件。维基百科页面:http://en.wikipedia.org/wiki/On-premises_software (译者注) 151 | 152 | #####[^2] 银弹( _Silver Bullet_ )的典故在 IT 经典图书《人月神话——软件项目管理之道》( _The Mythical Man-Month: Essays on Software Engineering_ )中提到过。在古老的传说中,只有银弹才能杀死巫士、巨人、狼人等。一般是指威力无穷或者效率高超的武器/技术,或者万灵药,或者是妙手回春之高招。(译者注) 153 | 154 | ---- 155 | 这篇文章由[ Solomon Hykes ](http://blog.docker.io/author/solomon/)发表,点击[此处](http://blog.docker.io/2013/11/docker-0-7-docker-now-runs-on-any-linux-distribution/)可查阅原文。 156 | 157 | The article was contributed by [Solomon Hykes](http://blog.docker.io/author/solomon/), click [here](http://blog.docker.io/2013/11/docker-0-7-docker-now-runs-on-any-linux-distribution/) to read the original publication. 158 | -------------------------------------------------------------------------------- /docker-15-tips.md: -------------------------------------------------------------------------------- 1 | ![Docker 15 个要点](http://docker.u.qiniudn.com/docker-15-tips.jpg) 2 | 3 | #15分钟,掌握15个Docker要点 4 | 5 | 6 | ##1. 获取最近运行容器的id 7 | 8 | 这是我们经常会用到的一个操作,按照官方示例,你可以这样做: 9 | 10 | $ ID=$(docker run ubuntu echo hello world) 11 | hello world 12 | $ docker commit $ID helloworld 13 | fd08a884dc79 14 | 15 | 这种方式在编写脚本的时候很有用,比如你想在脚本中批量获取id,然后进一步操作。但是这种方式要求你必须给ID赋值,如果是直接敲命令,这样做就不太方便了。 16 | 这时,你可以换一种方式: 17 | 18 | $ alias dl=’docker ps -l -q’ 19 | $ docker run ubuntu echo hello world 20 | hello world 21 | $ dl 22 | 1904cf045887 23 | $ docker commit `dl` helloworld 24 | fd08a884dc79 25 | 26 | `docker ps -l -q`命令将返回最近运行的容器的id,通过设置别名(alias),dl命令就是获取最近容器的id。这样,就无需再输入冗长的docker ps -l -q命令了。通过两个斜引号``,可以获取dl命令的值,也就是最近运行的容器的id。 27 | 28 | 29 | ##2.尽量在Dockerfile中指定要安装的软件,而不用Docker容器的shell直接安装软件 30 | 31 | 说实话,我有时候也喜欢在shell中安装软件,也许你也一样,喜欢在shell中把所有软件安装都搞定。但是,搞来搞去,最后还是发现,你还是需要在Doockerfile中指定安装文件。在shell中安装软件,你要这样做: 32 | 33 | $ docker run -i -t ubuntu bash #登陆到docker容器 34 | root@db0c3967abf8:/# 35 | 36 | 然后输入下面的命令来安装文件: 37 | 38 | apt-get install postgresql 39 | 40 | 然后再调用exit: 41 | 42 | root@db0c3978abf8:/# exit 43 | 44 | 退出docker容器,再给docker commit命令传递一个复杂的JSON字符串来提交新的镜像: 45 | 46 | $ docker commit -run=”{“Cmd”:[“postgres”,”-too -many -opts”] }” `dl` postgres 47 | 48 | 太麻烦了,不是吗?还是在Dockerfile中指定安装文件吧,只要两个步骤: 49 | 50 | 1.在一个小巧的Dockerfile中,指定当前操作的镜像为FROM命令的参数 51 | 2.然后在Dockerfile中指定一些docker的命令,如CMD, ENTERPOINT, VOLUME等等来指定安装的软件 52 | 53 | 54 | ##3.超-超-超级用户 55 | 56 | 你可能需要一直用超级用户来操作docker,就像早期示例里一直提示的: 57 | 58 | # 添加docker用户组 59 | $ sudo groupadd docker 60 | # 把自己加到docker用户组中 61 | $ sudo gpasswd -a myusername docker 62 | # 重启docker后台服务 63 | $ sudo service docker restart 64 | # 注销,然后再登陆 65 | $ exit 66 | 67 | Wow!连续三个sudo!三次化身“超级用户”,真可谓是“超-超-超级用户”啊!别担心,设置完毕,以后你就再也不用打那么多sudo了! 68 | 69 | 70 | ##4. 清理垃圾 71 | 72 | 如果你想删除所有停止运行的容器,用这个命令: 73 | 74 | $ docker rm $(docker ps -a -q) 75 | 76 | 顺便说一句,docker ps命令很慢,不知道为啥这么慢,按理说Go语言是很快的啊。 77 | `docker ps -a -q`命令列出所有容器的id,然后根据id删除容器。docker rm命令遇到正在运行的容器就会失效,所以这个命令完美的删除了所有没在运行的容器。 78 | 79 | 80 | 81 | ##5. docker inspect输出结果的解析利器:jq 82 | 83 | 要对docker inspect的输出结果进行过滤,一般情况下,用grep命令,你需要这样操作: 84 | 85 | $docker inspect `dl` | grep IPAddress | cut -d ‘“‘ -f 4 172.17.0.52 86 | 87 | 哦!看上去很复杂,用jq吧,专业解析docker inspect输出结果,具有更强的可读性,方便易用: 88 | 89 | $docker inspect `dl` | jq -r ‘.[0].NetworkSettings.IPAddress’ 172.17.0.52 90 | 91 | 其中第一个’.’代表所有的结果。’[0]’代表数组的第一个元素。就像JavaScript访问一个JSON对象一样,简单方便。 92 | 93 | 94 | ##6.镜像有哪些环境变量? 95 | 96 | 有时候,你需要知道自己创建的镜像有哪些环境变量。简单!只要这样: 97 | 98 | $ docker run ubuntu env 99 | 100 | 输出结果如下: 101 | 102 | HOME=/ 103 | PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin 104 | container=lxc 105 | HOSTNAME=5e1560b7f757 106 | 107 | 调用env查看环境变量,对于后面要讲到的“链接”(-link)很有用,在连接两个容器时候需要用到这些环境变量,具体请看最后一个要点“链接”。 108 | 109 | ##7.RUN命令 vs CMD命令 110 | 111 | Docker的新手用户比较容易混淆RUN和CMD这两个命令。 112 | RUN命令在构建(Build)Docker时执行,这时CMD命令不执行。CMD命令在RUN命令执行时才执行。我们来理清关系,假设Dockerfile内容如下: 113 | 114 | FROM thelanddownunder 115 | MAINTAINER crocdundee 116 | 117 | 118 | 我们要向系统中安装一些软件,那么: 119 | 120 | # docker build将会执行下面的命令: 121 | RUN apt-get update 122 | RUN apt-get install softwares 123 | # dokcer run默认执行下面的命令: 124 | CMD [“softwares”] 125 | 126 | Build时执行RUN,RUN时执行CMD,也就是说,CMD才是镜像最终执行的命令。 127 | 128 | 129 | ##8.CMD命令 vs ENTRYPOINT命令 130 | 131 | 又是两条容易混淆的命令!具体细节我们就不说了,举个例子,假设一个容器的Dockerfile指定CMD命令,如下: 132 | 133 | FROM ubuntu 134 | CMD [“echo”] 135 | 136 | 另一个容器的Dockerfile指定ENTRYPOINT命令,如下: 137 | 138 | FROM ubuntu 139 | ENTRYPOINT [“echo”] 140 | 141 | 运行第一个容器: 142 | 143 | docker run image1 echo hello 144 | 145 | 得到的结果: 146 | 147 | hello 148 | 149 | 运行第二个容器: 150 | 151 | docker run image2 echo hello 152 | 153 | 得到的结果: 154 | 155 | echo hello 156 | 157 | 看到不同了吧?实际上,CMD命令是可覆盖的,docker run后面输入的命令与CMD指定的命令匹配时,会把CMD指定的命令替换成docker run中带的命令。而ENTRYPOINT指定的命令只是一个“入口”,docker run后面的内容会全部传给这个“入口”,而不是进行命令的替换,所以得到的结果就是“echo hello”。 158 | 159 | 160 | ##9.Docker容器有自己的IP地址吗? 161 | 162 | 刚接触Docker的人或许会有这样的疑问:Docker容器有自己的IP地址吗?Docker容器是一个进程?还是一个虚拟机?嗯...也许两者兼具?哈哈,其实,Docker容器确实有自己的IP,就像一个具有IP的进程。只要分别在主机和Docker容器中执行查看ip的命令就知道了。 163 | 164 | 查看主机的ip: 165 | 166 | $ ip -4 -o addr show eth0 167 | 168 | 得到结果: 169 | 170 | 2: eth0 inet 162.243.139.222/24 171 | 172 | 查看Docker容器的ip: 173 | 174 | $ docker run ubuntu ip -r -o addr show eth0 175 | 176 | 得到结果: 177 | 178 | 149: eth0 inet 172.17.0.43/16 179 | 180 | 两者并不相同,说明Docker容器有自己的ip。 181 | 182 | 183 | ##10.基于命令行的瘦客户端,使用UNIX Socket和Docker后台服务的REST接口进行通信 184 | 185 | Docker默认是用UNIX socket通信的,一直到大概0.5、0.6的版本还是用端口来通信,但现在则改成UNIX socket,所以从外部无法控制Docker容器的内部细节。下面我们来搞点有趣的事情,从主机链接到docker的UNIX socket: 186 | 187 | # 像HTTP客户端一样连接到UNIX socket 188 | $ nc -U / /var/run/docker.sock 189 | 190 | 连接成功后,输入: 191 | 192 | GET /images/json HTTP/1.1 193 | 194 | 输入后连敲两个回车,第二个回车表示输入结束。然后,得到的结果应该是: 195 | 196 | HTTP/1.1 200 OK 197 | Content-Type: application/json 198 | Date: Tue, 05 Nov 2013 23:18:09 GMT 199 | Transfer-Encoding: chunked 200 | 16aa 201 | [{“Repository”:”postgres”,”Tag”:”...... 202 | 203 | 有一天,我不小心把提交的名称打错了,名字开头打成”-xxx”(我把命令和选项的顺序搞混了),所以当我删除的时候出了问题,docker rm -xxx,会把-xxx当成参数而不是镜像的名称。所以我只得通过socket直接连到容器来调用REST Server把错误的东西删掉。 204 | 205 | ##11.把镜像的依赖关系绘制成图 206 | 207 | docker images命令有一个很拉风的选项:-viz,可以把镜像的依赖关系绘制成图并通过管道符号保存到图片文件: 208 | 209 | # 生成一个依赖关系的图表 210 | $ docker images -viz | dot -T png -o docker.png 211 | 212 | 这样,主机的当前路径下就生成了一张png图,然后,用python开启一个微型的HTTP服务器: 213 | 214 | python -m SimpleHTTPServer 215 | 216 | 然后在别的机器上用浏览器打开: 217 | 218 | http://machinename:8000/docker.png 219 | 220 | OK,依赖关系一目了然! 221 | 222 | (译者注:要使用dot命令,主机要安装graphviz包。另外,如果主机ip没有绑定域名,machinename换成主机的ip即可。) 223 | 224 | 225 | ##12.Docker把东西都存到哪里去了? 226 | 227 | Docker实际上把所有东西都放到/var/lib/docker路径下了。切换成super用户,到/var/lib/docker下看看,你能学到很多有趣的东西。执行下面的命令: 228 | 229 | $ sudo su 230 | # cd /var/lib/docker 231 | # ls -F 232 | containers/ graph/ repositories volumes/ 233 | 234 | 可以看到不少目录,containers目录当然就是存放容器(container)了,graph目录存放镜像,文件层(file system layer)存放在graph/imageid/layer路径下,这样你就可以看看文件层里到底有哪些东西,利用这种层级结构可以清楚的看到文件层是如何一层一层叠加起来的。 235 | 236 | ##13.Docker源代码:Go, Go, Go, Golang! 237 | 238 | Docker的源代码全部是用Go语言写的。Go是一门非常酷的语言。其实,不只是Docker,很多优秀的软件都是用Go写的。对我来说,Docker源文件中,有4个是我非常喜欢阅读的: 239 | 240 | #####commands.go 241 | docker的命令行接口,是对REST API的一个轻量级封装。Docker团队不希望在命令中出现逻辑,因此commands.go只是向REST API发送指令,确保其较小的颗粒性。 242 | 243 | #####api.go 244 | REST API的路由(接受commands.go中的请求,转发到server.go) 245 | 246 | #####server.go 247 | 大部分REST API的实现 248 | 249 | #####buildfile.go 250 | Dockerfile的解析器 251 | 252 | 有的伙计惊叹”Wow!Docker是怎么实现的?!我无法理解!”没关系,Docker是开源软件,去看它的源代码就可以了。如果你不太清楚Dockerfile中的命令是怎么回事,直接去看buildfile.go就明白了。 253 | 254 | 255 | ##14.运行几个Docker后台程序,再退出容器,会发生什么? 256 | 257 | OK,倒数第二个要点。如果在Docker中运行几个后台程序,再退出Docker容器,会发生什么?答案是:不要这么做!因为这样做后台程序就全丢了。 258 | 259 | Dockerfile中用RUN命令去开启一个后台程序,如: 260 | 261 | RUN pg_ctl start 262 | 263 | 这样的话,RUN命令开启的后台程序就会丢失。调用容器的bash连到容器的shell: 264 | 265 | $ docker run -i -t postgresimage bash 266 | 267 | 然后调用 ps aux查看进程,你会发现postgres的进程并没有跑起来。 268 | RUN命令会影响文件系统。因此,不要再Dockerfile中用启动后台程序,要把后台程序启动成前台进程。或者,像一些高手提议的那样,写一个启动脚本,在脚本中启动这些后台程序或进程。 269 | 270 | ##15.容器之间进行友好沟通:链接 271 | 272 | 这是最拉风的功能!我把它留到最后压轴!这是0.6.5中最重要的新功能,我们前面已经提过两次了。运行一个容器,给它一个名称,在下面的例子中,我们通过-name参数给容器指定名称”loldb”: 273 | 274 | $ docker run -d -name loldb loldbimage 275 | 276 | 再运行另一个容器,加上-link参数来连接到第一个容器(别名为loldb),并给第二个容器也指定一个别名(这里用的是cheez): 277 | 278 | $ docker run -link /loldb:cheez otherimage env 279 | 280 | 顺便得到cheez的环境变量: 281 | 282 | CHEEZ_PORT=tcp://172.17.0.8:6379 283 | CHEEZ_PORT_1337_TCP=tcp://172.17.0.8.6379 284 | CHEEZ_PORT_1337_TCP_ADDR=tcp://172.17.0.12 285 | CHEEZ_PORT_1337_TCP_PORT=6379 286 | CHEEZ_PORT_1337_TCP_PROTO=tcp 287 | 288 | 289 | 这样,我们就在两个容器间建立起一个网络通道(bridge),基于此,我们可以建立一个类似rails的程序:一个容器可以访问数据库容器而不对外暴露其他接口。非常酷!数据库容器只需要知道第一个容器的别名(在本例中为cheez)和要打开的端口号。所以数据库容器也可以env命令来查看这个端口是否打开。 290 | 291 | ---- 292 | 这篇文章由 [Brian Morearty](https://twitter.com/BMorearty) 发表,点击 [此处](http://www.youtube.com/watch?v=BJT9bA64Hcc) 观看讲座视频,或下载讲座 [PPT](http://docker.u.qiniudn.com/15_Docker_Tips_in_5_Minutes.pdf)。 293 | -------------------------------------------------------------------------------- /docker-closes-15-m-dollars-series-b-foundings.md: -------------------------------------------------------------------------------- 1 | #DOCKER获得B轮1500万美元融资 2 | 3 | 我们高兴地[宣布](http://www.businesswire.com/news/home/20140122005497/en/Docker-Closes-15M-Series-Funding#.Ut_b3hDTmUl) [ Docker Inc. ](http://www.docker.com/) 完成了 1500 万美元的 B 轮融资。该轮融资由[ Greylock Partners ](http://www.greylock.com/)领投,[ Insight Venture Partners ](http://www.insightpartners.com/)和我们 A 轮投资者[ Benchmark ](http://www.crunchbase.com/financial-organization/benchmark-2)( Peter Fenton )、[ Trinity Ventures ](http://www.trinityventures.com/)( Dan Scholnick )及[ Jerry Yang/AME Cloud Ventures ](http://www.amecloudventures.com/)跟投。 4 | 5 | 此轮融资因为以下两大原因而备受瞩目。 6 | 7 | 首先,我们能以这样高的估值吸引到顶级风投充分证明了人们对 Docker 充满信心。更重要的是,这是对 Docker [开发团队](http://www.docker.io/team/)的出色工作的认可,也是对广泛的(由社区成员、合作伙伴、平台及发行商构建的)[生态系统](http://www.docker.com/about_docker/)的认可。当然,这也是对[ Solomon ](http://www.youtube.com/watch?v=3N3n9FzebAA)的远见卓识的肯定[1]。 8 | 9 | 其次,这轮融资为 Docker 更上一层楼提供了董事会支持和资金支持。从本轮融资规模到近期我们的人员[招聘](http://blog.docker.io/2014/01/open-source-veteran-roger-egan-joins-docker-team/),清晰地让我们认识到 Docker 一定是下一代计算领域重要的元素。也让我们更加充满斗志。这轮融资让我们知道自己有此实力。 10 | 11 | 下面我们来揭开本轮融资背后的更多细节: 12 | 13 | 1. 本轮融资及新的合作伙伴 14 | 15 | 2. Docker 生态系统的现状 16 | 17 | 3. 我们的未来计划 18 | 19 | 20 | ##本轮融资细节 21 | 22 | 本轮我们的融资高达一千五百万美元,由 Greylock Ventures 的[ Jerry Chen ](http://www.greylock.com/teams/50-Jerry-Chen)领投完成,他也即将加入我们的董事会。 23 | 24 | Greylock Ventures 是一家[顶级](http://www.forbes.com/sites/tomiogeron/2013/05/08/the-top-ten-in-venture-capital-today-midas/)投资公司,在投资开源软件 (例如 Red Hat 和 Cloudera )方面经验丰富,最近的一系列投资也让人印象深刻,包括 LinkedIn 、 Facebook 、Palo Alto Networks 和 Workday 等。 25 | 26 | 在加入 Greylock Ventures 之前,Jerry 在 VMware 担任副总裁,负责 Cloud and Application Services 。在他和其他高管的领导下,VMware 的员工人数由400人增加到一万五千多人,收入高达五十亿美元。在 VMware 的九年里,Jerry 发布了数十项产品(包括多个 “1.0” 发布),启动两个全新的业务部门。 Jerry 在视觉化、产品化以及规模化方面积累了宝贵的财富,并以其远见、经验和对 Docker 的价值让我们印象深刻。对于 Greylock 为何投资Docker,Jerry 从其视角进行了解读,点击[此处](http://greylockvc.com/post/74175923348/our-investment-in-docker)阅读他的博客。 27 | 28 | 除了 Greylock ,我们还幸运地得到了Insight Venture Partners (以下简称 IVP )的青睐。IVP 的投资历史十分耀眼,曾为诸如 Twitter 、 Chegg 、 New Relic 、 Parallels 和 Flipboard 等公司的发展提供支持。 IVP 的联合创始人[ Jerry Murdock ](http://www.insightpartners.com/team/#!jerry-murdock) 也加入了我们的董事会。 Jerry 也富有远见,他说:“ Docker 是 Dev/Ops 梦想成真的最佳注解,他们以一种有力、高效、可量化的方式改变了开发者和运维人员的世界。” 29 | 30 | 最后我们非常感谢从 A 轮融资伊始就一直支持我们的投资者和董事会成员们,包括 Benchmark 的 Peter Fenton 、 Trinity 的 Dan Scholnick 、 Jerry Yang 及其他人。 31 | 32 | 鉴于目前在我们的董事会里已经有了三位 “ Jerry ” ,加上我的名字,我们现在可是IT行业的 Ben & Jerry’s 了[2]。 33 | 34 | ![Smaller icon](http://docker.u.qiniudn.com/ben-jerry.jpeg "Title here") 35 | 36 | ##我们的生态系统 37 | 38 | Docker 生态系统持续迅速发展。在我们成立后的最初九个月里,我们被下载40万次,得到三百多位贡献者的欢迎,在公开 index 中有超过5000个基于 Docker 的应用发布。 eBay 、 Yandex 、Mailgun 、 CloudFlare 和 Baidu 等公司也公开[讨论](http://www.docker.com/about_docker/usecases/)他们对 Docker 的使用或支持。社区(的发展)促使 ( Docker )被整合到 Chef 、 Puppet 、 Salt 、Jenkin 及其他重要的(开发)工具中。现在,Docker [线下聚会](https://www.docker.io/meetups/) 小组已经遍及全球40多个城市。最让我们兴奋的是 Docker 被[ Red Hat ](http://www.redhat.com/about/news/press-archive/2013/9/red-hat-and-dotcloud-collaborate-on-docker-to-bring-next-generation-linux-container-enhancements-to-openshift)、[ Google Compute Engine ](http://googlecloudplatform.blogspot.com/2013/12/google-compute-engine-is-now-generally-available.html) 、[ Rackspace ](http://developer.rackspace.com/blog/zero-to-peanut-butter-docker-time-in-78-seconds.html)和[ OpenStack ](http://blog.docker.io/tag/openstack-2/)等平台广泛使用。 39 | 40 | ####Docker 生态系统 41 | 42 | ![Smaller icon](http://docker.u.qiniudn.com/docker-ecosystem.jpeg "Title here") 43 | 44 | ####Docker 线下聚会小组 45 | 46 | ![Smaller icon](http://docker.u.qiniudn.com/docker-meetup.png "Title here") 47 | 48 | ##我们将如何使用资金 49 | 50 | 如上所述,我们相信自己获得了绝佳的机会来从根本上改变代码构建、部署和规模化的方式。我们期望这些投资能被合理使用。 51 | 52 | 下一年,这些投资将被计划用于以下三个主要领域: 53 | 54 | 1) 投资 Docker 开源项目 55 | 56 | 我们对于 Docker 过去几个月取得的成就感到激动,这归功于 Docker 团队和我们不可思议的[社区](http://www.docker.io/community/),有超过300位[贡献者](https://github.com/dotcloud/docker)为 Docker 贡献代码。不过我们仍然有很多工作要做,包括发布 Docker 1.0 版本、支持其他平台、隔离 、存储和网络等众多功能,以及促进社区的和谐发展。因此,我们将为必需的程序说明书、培训、线下聚会和会议等提供资助,这样所有人都可以开始使用 Docker 。我们正在强化我们的[团队](http://www.docker.io/team/),我们也期待新同仁加入。 57 | 58 | 2)构建社区平台 59 | 60 | 为了促进 Docker 生态系统的健康发展,我们需要扩展平台,从而让人们轻松地查找、发布和使用 Docker 容器。我们将加大公共 Docker 容器服务的相关基础设施投入,改进Dockerfiles与GitHub等源代码系统的整合,为公共 Docker 容器服务提供开发者ID、时间戳和数字签名等服务,从而任何人都可以查看公开容器的来源和出处。 61 | 62 | 3)强化商业能力 63 | 64 | 基于 Docker 本身免费、开源特质,我们加紧启动围绕 Docker 的托管服务和为 Docker 提供商业支持。我们最近聘请了[ James Turnbull ](http://www.jamesturnbull.net/) (前 Puppet 副总裁,负责技术操作和支持业务)来强化我们的支持团队。我们也聘请了[ Roger Egan ](http://www.linkedin.com/pub/roger-egan/5/622/548)(前 Red Hat副总裁,负责北美渠道/中小企业),以建设我们的销售团队和合作网络。能获得这两位开源领域的牛人的加入,我们何其有幸!我们的工程师团队也强化了托管服务,我们希望企业用户能够方便地将 Docker 部署在他们的产品中,[合作伙伴](http://www.docker.com/partners/)也能围绕 Docker 建立起牢固的商业发展。 65 | 66 | ##结语 67 | 68 | 我们度过了无比奇妙的2013年,我们期待更加精彩的2014以及未来。 69 | 70 | 有了这笔新投资,我们能够围绕 Docker 来建设一家值得我们努力与支持的公司。诚挚地感谢你们帮助我们达到这个里程碑。我们的前路更精彩! 71 | 72 | —— 73 | 74 | [1] Solomon 和 dotCloud 的故事十分引人入胜,Peter Fento曾经说过: 75 | > 正是 Solomon 激励我们在 Docker 还是 dotCloud 的时代就进行投资。要将传统商业改造为一项纯净的开源项目,以及招募到像 Ben 这样能干的人,都需要极大的勇气。和 Solomon 一起工作是一件鼓舞人心的事情。 76 | 77 | [2] Ben & Jerry's 是联合利华旗下生产冰激凌、冻酸奶和冰沙的乳品公司。(译者注) 78 | 79 | -------------------------------------------------------------------------------- /docker-http-proxy-with-golang-en.md: -------------------------------------------------------------------------------- 1 | ##Writing a simple HTTP proxy using Golang 2 | 3 | The [goproxy](https://github.com/elazarl/goproxy) is a light weight http proxy library, which allows you to easily write a [proxy program](https://github.com/dockboard/docker-proxy) for [Docker](http://docker.io/), here is the code: 4 | 5 | 6 | ``` 7 | package main 8 | 9 | import ( 10 | "github.com/elazarl/goproxy" 11 | "net/http" 12 | "regexp" 13 | ) 14 | 15 | func main() { 16 | proxy := goproxy.NewProxyHttpServer() 17 | proxy.OnRequest().DoFunc( 18 | func(r *http.Request, ctx *goproxy.ProxyCtx) (*http.Request, *http.Response) { 19 | match, _ := regexp.MatchString("^*.docker.io$", r.URL.Host) 20 | if match == false { 21 | return r, goproxy.NewResponse(r, goproxy.ContentTypeText, http.StatusForbidden, 22 | "The proxy is used exclusively to download docker image, please don't abuse it for any purpose.") 23 | } else { 24 | return r, nil 25 | } 26 | }) 27 | proxy.Verbose = false 28 | http.ListenAndServe(":8384", proxy) 29 | } 30 | ``` 31 | 32 | 33 | The program checks the target URL on each HTTP request, if the target is not docker.io or any of its sub sites, it will return an error. The purpose is to protect the server from abusing or misusing which possibly leads to being banned by Great Firewall because it's used to visit websites which are unaccessible in mainland China. 34 | 35 | 36 | ##Writing the init.d script for Ubuntu 37 | 38 | 39 | We have to write the init.d script file to let the proxy service run as a daemon in Ubuntu: 40 | 41 | 42 | ``` 43 | #!/bin/sh 44 | 45 | ### BEGIN INIT INFO 46 | # Provides: dockboard.org 47 | # Required-Start: $syslog $remote_fs 48 | # Required-Stop: $syslog $remote_fs 49 | # Default-Start: 2 3 4 5 50 | # Default-Stop: 0 1 6 51 | # Short-Description: Create lightweight http proxy for Docker daemon. 52 | # Description: 53 | # Author: Meaglith Ma 54 | # Email: genedna@gmail.com 55 | # Website: http://www.dockboard.org 56 | ### END INIT INFO 57 | 58 | BASE=$(basename $0) 59 | 60 | DOCKER_PROXY=/usr/bin/$BASE 61 | DOCKER_PROXY_PIDFILE=/var/run/$BASE.pid 62 | DOCKER_PROXY_OPTS= 63 | 64 | PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin 65 | 66 | # Check docker is present 67 | if [ ! -x $DOCKER_PROXY ]; then 68 | exit 1 69 | fi 70 | 71 | fail_unless_root() { 72 | if [ "$(id -u)" != '0' ]; then 73 | exit 1 74 | fi 75 | } 76 | 77 | case "$1" in 78 | start) 79 | fail_unless_root 80 | start-stop-daemon --start --background \ 81 | --exec "$DOCKER_PROXY" \ 82 | --pidfile "$DOCKER_PROXY_PIDFILE" \ 83 | -- -d -p "$DOCKER_PROXY_PIDFILE" \ 84 | $DOCKER_PROXY_OPTS 85 | ;; 86 | 87 | stop) 88 | fail_unless_root 89 | start-stop-daemon --stop \ 90 | --pidfile "$DOCKER_PROXY_PIDFILE" 91 | log_end_msg $? 92 | ;; 93 | 94 | restart) 95 | fail_unless_root 96 | docker_pid=`cat "$DOCKER_PROXY_PIDFILE" 2>/dev/null` 97 | [ -n "$docker_pid" ] \ 98 | && ps -p $docker_pid > /dev/null 2>&1 \ 99 | && $0 stop 100 | $0 start 101 | ;; 102 | 103 | force-reload) 104 | fail_unless_root 105 | $0 restart 106 | ;; 107 | 108 | status) 109 | status_of_proc -p "$DOCKER_PROXY_PIDFILE" "$DOCKER" docker 110 | ;; 111 | 112 | *) 113 | echo "Usage: $0 {start|stop|restart|status}" 114 | exit 1 115 | ;; 116 | esac 117 | 118 | exit 0 119 | ``` 120 | 121 | 122 | ##Modify docker’s configuration to use HTTP proxy in Ubuntu 123 | 124 | 125 | Let’s add the http proxy environment variables to /etc/init /docker.conf: 126 | 127 | ``` 128 | description "Docker daemon" 129 | 130 | start on filesystem and started lxc-net 131 | stop on runlevel [!2345] 132 | 133 | respawn 134 | 135 | env HTTP_PROXY="http://192.241.209.203:8384" 136 | 137 | script 138 | DOCKER=/usr/bin/$UPSTART_JOB 139 | DOCKER_OPTS= 140 | if [ -f /etc/default/$UPSTART_JOB ]; then 141 | . /etc/default/$UPSTART_JOB 142 | fi 143 | "$DOCKER" -d $DOCKER_OPTS 144 | end script 145 | ``` 146 | 147 | 148 | Or we can remove the comment on http_proxy in etc/default/docker: 149 | 150 | ``` 151 | # If you need Docker to use an HTTP proxy, it can also be specified here. 152 | export http_proxy=http://192.241.209.203:8384/ 153 | ``` 154 | 155 | 156 | Restart docker and it will download images through the proxy 192.241.209.203:8384 157 | 158 | 159 | ###Available proxies 160 | 161 | ``` 162 | http://192.241.209.203:8384 163 | ``` 164 | 165 | 166 | The [dockerboard](http://www.dockboard.org/) is now providing a proxy service (deployed on DigitalOcean’s VPS) for the domestic Chinese users to use and study [Docker](http://docker.io/). The proxy is not guaranteed to be available 24/7. If you encounter any problem, please contact the dockboard's [official Weibo account](http://weibo.com/dockboard) for consultation. 167 | 168 | 169 | If you have any idle VPS and you would like to deploy a proxy to support Chinese docker lovers, we would be very grateful and happy to provide total technical support. To make the greatness, please contact: [meaglith.ma@aliyun.com](mailto:meaglith.ma@aliyun.com) 170 | -------------------------------------------------------------------------------- /docker-http-proxy-with-golang.md: -------------------------------------------------------------------------------- 1 | ##使用 Golang 编写一个简单的 HTTP 代理 2 | 3 | [goproxy](https://github.com/elazarl/goproxy) 是一个轻量级的 HTTP 代理库,可以很容易的编写一个仅供 [Docker](http://docker.io) 使用的代理 [程序](https://github.com/dockboard/docker-proxy) 。 4 | 5 | ``` 6 | package main 7 | 8 | import ( 9 | "github.com/elazarl/goproxy" 10 | "net/http" 11 | "regexp" 12 | ) 13 | 14 | func main() { 15 | proxy := goproxy.NewProxyHttpServer() 16 | proxy.OnRequest().DoFunc( 17 | func(r *http.Request, ctx *goproxy.ProxyCtx) (*http.Request, *http.Response) { 18 | match, _ := regexp.MatchString("^*.docker.io$", r.URL.Host) 19 | if match == false { 20 | return r, goproxy.NewResponse(r, goproxy.ContentTypeText, http.StatusForbidden, 21 | "The proxy is used exclusively to download docker image, please don't abuse it for any purpose.") 22 | } else { 23 | return r, nil 24 | } 25 | }) 26 | proxy.Verbose = false 27 | http.ListenAndServe(":8384", proxy) 28 | } 29 | ``` 30 | 31 | 程序在每次 HTTP 的请求过程中都检测目标地址的 URL,如果不是 docker.io 或子站会返回一个错误信息。这为了避免使用代理访问其它的网站,致使服务器被墙。 32 | 33 | ##编写 Ubuntu init.d 的启动脚本 34 | 35 | 为了保证服务在后台运行,编写 Ubuntu init.d 的启动脚本管理 Proxy 服务。 36 | ``` 37 | #!/bin/sh 38 | 39 | ### BEGIN INIT INFO 40 | # Provides: dockboard.org 41 | # Required-Start: $syslog $remote_fs 42 | # Required-Stop: $syslog $remote_fs 43 | # Default-Start: 2 3 4 5 44 | # Default-Stop: 0 1 6 45 | # Short-Description: Create lightweight http proxy for Docker daemon. 46 | # Description: 47 | # Author: Meaglith Ma 48 | # Email: genedna@gmail.com 49 | # Website: http://www.dockboard.org 50 | ### END INIT INFO 51 | 52 | BASE=$(basename $0) 53 | 54 | DOCKER_PROXY=/usr/bin/$BASE 55 | DOCKER_PROXY_PIDFILE=/var/run/$BASE.pid 56 | DOCKER_PROXY_OPTS= 57 | 58 | PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin 59 | 60 | # Check docker is present 61 | if [ ! -x $DOCKER_PROXY ]; then 62 | exit 1 63 | fi 64 | 65 | fail_unless_root() { 66 | if [ "$(id -u)" != '0' ]; then 67 | exit 1 68 | fi 69 | } 70 | 71 | case "$1" in 72 | start) 73 | fail_unless_root 74 | start-stop-daemon --start --background \ 75 | --exec "$DOCKER_PROXY" \ 76 | --pidfile "$DOCKER_PROXY_PIDFILE" \ 77 | -- -d -p "$DOCKER_PROXY_PIDFILE" \ 78 | $DOCKER_PROXY_OPTS 79 | ;; 80 | 81 | stop) 82 | fail_unless_root 83 | start-stop-daemon --stop \ 84 | --pidfile "$DOCKER_PROXY_PIDFILE" 85 | log_end_msg $? 86 | ;; 87 | 88 | restart) 89 | fail_unless_root 90 | docker_pid=`cat "$DOCKER_PROXY_PIDFILE" 2>/dev/null` 91 | [ -n "$docker_pid" ] \ 92 | && ps -p $docker_pid > /dev/null 2>&1 \ 93 | && $0 stop 94 | $0 start 95 | ;; 96 | 97 | force-reload) 98 | fail_unless_root 99 | $0 restart 100 | ;; 101 | 102 | status) 103 | status_of_proc -p "$DOCKER_PROXY_PIDFILE" "$DOCKER" docker 104 | ;; 105 | 106 | *) 107 | echo "Usage: $0 {start|stop|restart|status}" 108 | exit 1 109 | ;; 110 | esac 111 | 112 | exit 0 113 | ``` 114 | 115 | ##Ubuntu 中修改 Docker 的配置文件使用 HTTP Proxy 116 | 117 | 修改 /etc/init/docker.conf 加入 http proxy 的环境变量。 118 | 119 | ``` 120 | description "Docker daemon" 121 | 122 | start on filesystem and started lxc-net 123 | stop on runlevel [!2345] 124 | 125 | respawn 126 | 127 | env HTTP_PROXY="http://192.241.209.203:8384" 128 | 129 | script 130 | DOCKER=/usr/bin/$UPSTART_JOB 131 | DOCKER_OPTS= 132 | if [ -f /etc/default/$UPSTART_JOB ]; then 133 | . /etc/default/$UPSTART_JOB 134 | fi 135 | "$DOCKER" -d $DOCKER_OPTS 136 | end script 137 | ``` 138 | 139 | 或者是修改 /etc/default/docker 文件,取消注释 http_proxy 的部分。 140 | 141 | ``` 142 | # If you need Docker to use an HTTP proxy, it can also be specified here. 143 | export http_proxy=http://192.241.209.203:8384/ 144 | ``` 145 | 146 | 重启 Docker 的服务后下载 images 就会通过 192.241.209.203:8384 这个代理进行访问。 147 | 148 | 149 | ## 可用的代理地址 150 | 151 | ``` 152 | http://192.241.209.203:8384 153 | ``` 154 | 155 | 目前 [dockboard](http://www.dockboard.org) 为了方便国内用户使用和学习 [docker](http://docker.io) 技术,使用 [DigitalOcean](http://www.digitalocean.com) 的 VPS 架设了一个代理。代理地址不保证 7x24 小时稳定,如果遇到网络问题,请咨询我们的微博账号:[Docker中文社区](http://weibo.com/dockboard)。 156 | 157 | 如果开发者有闲置的 VPS 愿意架设 Docker 的代理为社区提供支持,我们非常愿意提供技术帮助,请联络:meaglith.ma@aliyun.com。 158 | -------------------------------------------------------------------------------- /docker-segmentfault-qa-sub-site.md: -------------------------------------------------------------------------------- 1 | ![Docker 技术问答子站](http://docker.u.qiniudn.com/docker-segmentfault-qa-sub-site.jpg) 2 | 3 | 通过 [Dockboard](http://www.dockboard.org) 团队和 [SegmentFault](http://segmentfault.com) 团队的合作,在 [SegmentFault](http://segmentfault.com) 开通了 [Docker](http://docker.io) 技术问答的 [子站](http://segmentfault.com/docker) 。 4 | 5 | [Docker](http://docker.io) 是 [Go](http://golang.org) 社区最受关注的产品之一,它使得虚拟化技术更容易使用。[Docker](http://docker.io) 正在努力建立一个生态环境,活跃的用户和社区是其中的重要组成部分。[Dockboard](http://www.dockboard.org) 努力编写和翻译中文的技术文章,组织 [Meetup](http://www.meetup.com/Docker-Beijing) 活动。 6 | 7 | 感谢 [SegmentFault](http://segmentfault.com) 开通 [Docker](http://docker.io) 技术问答的 [子站](http://segmentfault.com/docker),为大家交流 [Docker](http://docker.io) 技术提供了平台。我们更期待在 [SegmentFault](http://segmentfault.com) 的各种活动中贡献 [Docker](http://docker.io) 的话题和 [Docker](http://docker.io) 的技术支持。 8 | 9 | 我们期望更多的开发者加入到 [Docker](http://docker.io) 的社区建设中,如果有意可以联系 :meaglith.ma@aliyun.com 。 10 | -------------------------------------------------------------------------------- /fiona.md: -------------------------------------------------------------------------------- 1 | ##Fiona Feng 2 | -------------------------------------------------------------------------------- /fish-shell-docker-completion-mac-os.md: -------------------------------------------------------------------------------- 1 | ##在 Mac OS 10.9 上安装 Fish Shell 2 | 3 | [Fish](http://fishshell.com) 是一个不那么流行但是非常好用的交互式 Shell ,在 Mac OS 上可以使用 brew 命令进行安装,或者下载 [pkg](http://fishshell.com/files/2.1.0/fish.pkg) 文件进行安装。 4 | 5 | ``` 6 | brew install fish 7 | ``` 8 | 9 | 然后修改 /etc/shells 文件,把 fish 加入到文件的最后。 10 | 11 | ``` 12 | # List of acceptable shells for chpass(1). 13 | # Ftpd will not allow users to connect who are not using 14 | # one of these shells. 15 | 16 | /bin/bash 17 | /bin/csh 18 | /bin/ksh 19 | /bin/sh 20 | /bin/tcsh 21 | /bin/zsh 22 | /usr/local/bin/fish 23 | ``` 24 | 25 | 修改 终端工具 的 偏好配置,在 Shell 的打开方式中选择命令,输入框中写入 /usr/local/bin/fish 。重启 终端工具 后可以 fish 就替代了默认的 bash 。 26 | 27 | ##安装 Docker 的命令补全 28 | 29 | ``` 30 | mkdir ~/.config/fish/completions 31 | wget https://raw.github.com/barnybug/docker-fish-completion/master/docker.fish -O ~/.config/fish/completions/docker.fish 32 | ``` 33 | 34 | 输入 docker 命令后按 tab 键就可以看到命令补全的输出,输入命令的前几个字母的时候也可以按 tab 查看补全的信息。 35 | 36 | ![Docker completion in fish shell](http://docker.u.qiniudn.com/docker-fish-shell-completion.png) 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /how-to-deploy-your-own-private-docker-registry.md: -------------------------------------------------------------------------------- 1 | ![enter image description here][1] 2 | 3 | #How to Deploy your own Private Docker Registry 4 | #部署自己的私有Docker Registry 5 | 6 | Matthew Fisher, January 21, 2014 7 | 8 | Matthew Fisher, 2014年1月21日 9 | 10 | This blog post shows how you can deploy your own private Docker Registry behind your firewall with SSL encryption and HTTP authentication. A Docker Registry is a service which you can push Docker images to for storage and sharing. We will be installing the registry on Ubuntu, but it should work on any operating system that supports upstart. SSL encryption and HTTP basic authentication will be managed by Nginx, which will be a proxy server in front of the Docker Registry. Upstart will manage the gunicorn processes that will run the registry. We will also be using a LRU cache to reduce roundtrips to the storage backend. For this cache we will use Redis. 11 | 12 | 这篇博客讨论了如何部署一个带 SSL 加密、HTTP 验证并有防火墙防护的私有 [Docker Registry](https://github.com/dotcloud/docker-registry) 。[Docker Registry](https://github.com/dotcloud/docker-registry) 是一个存储和分享 [Docker](http://docker.io) 镜像的服务。本文中我们使用的操作系统是 [Ubuntu](http://www.ubuntu.com),任何支持 [Upstart](http://upstart.ubuntu.com/) 的系统都可以。我们用 [Nginx](http://nginx.org) 作为 [Docker Registry](https://github.com/dotcloud/docker-registry) 的前端代理服务器,同时也用 [Nginx](http://nginx.org) 完成 SSL 加密和基本的 HTTP 验证。我们用 [Gunicorn](http://gunicorn.org) 运行 [Docker Registry](https://github.com/dotcloud/docker-registry) 并用 [Upstart](http://upstart.ubuntu.com/) 管理 [Gunicorn](http://gunicorn.org)。我们还用 [Redis](http://redis.io) 实现一个 LRU(Least Recently Used,近期最少使用算法) 缓存机制来减少 [Docker Registry](https://github.com/dotcloud/docker-registry) 和硬盘之间的数据存取。 13 | 14 | 15 | ##Why do you need a Docker Registry? 16 | ##为什么需要Docker Registry? 17 | When you create new Docker images for use in your environment - whether that'd be a Redis server, a Hipache daemon, or an IRC logbot - you're going to want to store the images somewhere safe. Maybe you're working on a project where you also want to create a Docker image with Jenkins or Buildbot on each commit, bag and tag (read: docker commit && docker tag) the image, and then push that to the registry. But what if your code is proprietary, and you don't want to push that image to the public registry? Docker Inc. has already thought of that for you, and has created the docker-registry project. This project will allow you to push your own images to your own in-house registry. Woo! 18 | 19 | 当在自己的环境中创建 [Docker](http://docker.io) 镜像的时候,无论是装 [Redis](http://redis.io/),[Hipache](https://github.com/dotcloud/hipache),还是 IRC 协议的 [logbot](https://github.com/dannvix/Logbot) ,你都希望可以把镜像存到一个安全的地方。也许你项目中的 [Docker](http://docker.io) 镜像需要安装 [Jenkins](http://buildbot.net/),或者每次 commit 都跑一遍 [Buildbot](http://buildbot.net/),又或者给镜像打上 bag 和 tag (相关阅读:[docker commit](http://docs.docker.io/en/latest/reference/commandline/cli/#commit),[docker tag](http://docs.docker.io/en/latest/reference/commandline/cli/#tag)),再发送到 [Docker Registry](https://github.com/dotcloud/docker-registry)。可是如果镜像中的代码是私有的,你不想把镜像放到公共的 [Docker Registry](http://index.docker.io) 上呢?[Docker](http://docker.io) 公司已经想到了这一点,并因此建立了 [docker-registry](https://github.com/dotcloud/docker-registry) 项目。[docker-registry](https://github.com/dotcloud/docker-registry) 允许你把自己的镜像 [push](http://docs.docker.io/en/latest/reference/commandline/cli/#push) 到自己的 registry 中,酷! 20 | 21 | ***还没看bag tag的内容*** 22 | 23 | If you want to kick the proverbial tires, you can test the docker registry: 24 | 25 | 如果你想感受一下[docker registry](https://github.com/dotcloud/docker-registry),可以用公共的 [registry](http://index.docker.io) 来试试: 26 | 27 | $ docker pull samalba/docker-registry 28 | $ docker run -d -p 5000:5000 samalba/docker-registry 29 | # 我们先pull下来一个简单的镜像(或者自己做一个也可以) 30 | $ docker pull busybox 31 | $ docker tag busybox localhost:5000/busybox 32 | $ docker push localhost:5000/busybox 33 | 34 | 35 | This is great to get started working with the registry for testing, but this will be using plain HTTP. Anyone can push to your server as long as they have endpoint access, which is not good. Let's get started with setting up our own private registry for internal use. 36 | 37 | 对于 registry 入门,这个例子很有用,但是例子中仅用了一个简单的 HTTP 服务。任何知道服务器地址的人都可以随意 push 镜像,这不是个好方案。下面我们来建立自己的私有 registry 以供内部使用。 38 | 39 | 40 | ##Planning our Deployment 41 | ##准备自己的部署方案 42 | 43 | Before we spawn an Ubuntu server to start deploying the registry, let's consider some things… 44 | 我们要创建一个 Ubuntu 服务器来部署 registry,在此之前,我们先考虑几件事情... 45 | 46 | ###What Storage Backend? 47 | ###用什么作为后台存储? 48 | 49 | What storage backend do we want to use? Here's a short list of the supported backends for the registry: 50 | local: use the local filesystem 51 | s3: store inside an Amazon S3 bucket 52 | swift: store inside a Openstack Swift container 53 | glance: use Openstack's Glance project 54 | elliptics: use the Elliptics key-value store 55 | 56 | Sidenote: I created the backend for Openstack Swift. If you find any bugs with it, please feel free to file a bug on the registry's github page. 57 | 58 | 我们用什么来做后台存储呢?请看下面几种存储方案: 59 | 60 | - local:用本地存储 61 | - s3:存到 Amazon S3 的 bucket 62 | - swift:存到 OpenStack 的 Swift 容器 63 | - glance:使用 OpenStack 的 Glance 项目 64 | - elliptics:使用 Elliptics 的键值存储方案 65 | 66 | 这些方案的 python 脚本在 [这里](https://github.com/dotcloud/docker-registry/tree/master/lib/storage),大家可以参考。 67 | 68 | 注:Openstack Swift 这个方案是我自己写的,如果发现 bug,欢迎在 docker registry 的 gituhb 主页提出。 69 | 70 | 译者注:国内的开发者 [桂阳](http://weibo.com/u/1656755095) 贡献了存储在阿里云的 [方案](https://github.com/guiyang/docker-registry/blob/aliyun-oss/lib/storage/aliyun_oss.py)。 71 | 72 | ###Hosted or In-House Server? 73 | ###托管服务器还是用自己搭建服务器? 74 | 75 | Where do we want to host our docker registry? Do we want to use our own Openstack cluster, Amazon Web Services, Rackspace, or our own bare metal servers? Any option will work for us! 76 | 77 | 我们要把 docker registry 服务部署到哪里呢?用自己的 OpenStack 集群?Amazon 的网络服务?还是 Rackspace?或者自己购买服务器?答案是:用什么都行! 78 | 79 | One thing to consider when using cloud-hosted infrastructure is the advantage of using an external volume for your data. This gives you control over managing your own backups, which is a huge win for us. 80 | 81 | 使用云服务,我们可以使用可扩展的存储空间,便于我们管理自己的备份,非常方便。 82 | 83 | 84 | ###What Operating System? 85 | ###用什么操作系统? 86 | 87 | Since the docker registry is a python project, it's ridiculously simple to port over to other operating systems. You can quite easily write up a systemd config file, or launch it as a Windows Service. Because we will be installing it on Ubuntu, we will be using upstart to manage our gunicorn processes. 88 | 89 | I will be demonstrating the deployment process using the local storage backend, where all of our assets will be held on our own hardware. We have an internal Openstack cluster over here in our Vancouver office (we love Openstack!), so we will use that for our hosting solution. docker-internal.example.com will be the fully qualified domain name, and we will be using Ubuntu's 12.04.3 cloud image as the server. 90 | All right. Let's get down to deploying! 91 | 92 | docker registry 是用 python 写的,所以把它导入到各种操作系统中真是太简单了。你可以轻轻松松的写一个 [systemd配置文件](https://wiki.archlinux.org/index.php/systemd#Writing_custom_.service_files) ,或者把它做成 [Widnows服务](http://en.wikipedia.org/wiki/Windows_service) 。本例中,我们在 Ubuntu 上安装 docker registry,因此,我们用 [upstart](http://upstart.ubuntu.com/)来管理 Gunicorn 进程。 93 | 94 | 接下来的部署工作都在本地硬盘里进行。我们自己的办公室里有一个内部的 Openstack 集群(我爱 Openstack!),因此我们用它来作服务器托管,域名用 “docker-internal.example.com”,服务器系统则用 [Ubuntu Cloud image](http://cloud-images.ubuntu.com/releases/12.04.3/release/),版本为12.04.3。 95 | 96 | 万事俱备,开工! 97 | 98 | ###Boot the Server 99 | ###启动服务器 100 | 101 | First, let's boot up a server. Since I'll be using our internal Openstack cluster, I'll just use the nova client to boot up my server. If you're following this post line by line, here are the credentials you'll need to set up: 102 | 103 | 首先,启动服务器。因为我是用的内部 Openstack,我用 [nova客户端](https://github.com/openstack/python-novaclient) 来启动就可以了。如果你按照本例来操作,请在 .bashrc 文件中设置下面列出的验证信息: 104 | 105 | 106 | $ cat ~/.bashrc 107 | [...] 108 | export OS_AUTH_URL=http://******/v2.0 109 | export OS_TENANT_ID=****** 110 | export OS_TENANT_NAME="******" 111 | export OS_USERNAME=****** 112 | export OS_PASSWORD="******" 113 | [...] 114 | 115 | Once you set that up, test by running: 116 | 117 | 设置完成后,请用下面的命令测试一下: 118 | 119 | $ sudo pip install python-novaclient 120 | $ nova list 121 | 122 | Before we boot the server, let's upload the Ubuntu cloud image, as well as your own SSH key... 123 | 124 | 启动服务器之前,我们先上传 Ubuntu cloud image 和自己的 SSH Key 文件: 125 | 126 | $ nova keypair-add --pub-key ~/.ssh/id_rsa.pub bacongobbler 127 | $ sudo pip install python-glanceclient 128 | $ glance image-create --name ubuntu-12.04.3-server-cloudimg-amd64 --disk-format qcow2 --container-format bare --location http://cloud-images.ubuntu.com/releases/12.04.3/release/ubuntu-12.04-server-cloudimg-amd64-disk1.img 129 | 130 | And create a security group that allows external access to port 80 and 443... 131 | 132 | 再创建一个安全组,来允许外部对 80 和 443 端口的访问: 133 | 134 | $ nova secgroup-create web-server "security group for standard web servers" 135 | $ nova secgroup-add-rule web-server tcp 80 80 0.0.0.0/0 136 | $ nova secgroup-add-rule web-server tcp 443 443 0.0.0.0/0 137 | 138 | now we will create the volume, which will be 512GB in size. We will be using this to store our docker images: 139 | 140 | 现在,我们来创建一个 512G 的分区,用于存储我们的 docker 镜像: 141 | 142 | $ nova volume-create 512 --display-name docker-internal 143 | 144 | ***根据上下文,nova volume-create命令应该是分配了一个分区,因为后面用mount把这个512GB的分区挂在到了一个目录里*** 145 | Finally, we can boot the server! 146 | 147 | 最后,启动服务器吧! 148 | 149 | $ nova boot docker-internal --image ubuntu-12.04.3-server-cloudimg-amd64 --flavor m1.medium --security-groups web-server --key-name bacongobbler 150 | $ # do some grepping for the volume ID 151 | $ VOLUME_ID=$(nova volume-list | grep docker-internal | awk '{print $2}') 152 | $ nova volume-attach docker-internal $VOLUME_ID /dev/vdb 153 | $ nova floating-ip-list 154 | +----------------+--------------------------------------+---------------+------+ 155 | | Ip | Instance Id | Fixed Ip | Pool | 156 | +----------------+--------------------------------------+---------------+------+ 157 | | 192.168.68.222 | 79caf450-7b23-46bd-839a-abec7408a2c0 | 192.168.32.26 | nova | 158 | | 192.168.68.224 | a10cb949-09b6-4533-9733-860a5f8fdff4 | 192.168.32.19 | nova | 159 | | 192.168.68.225 | None | None | nova | 160 | | 192.168.68.236 | None | None | nova | 161 | | 192.168.68.237 | dc835a69-2894-4278-aebe-4f9ca6363724 | 192.168.32.12 | nova | 162 | | 192.168.68.238 | 4a8835b6-a318-44b5-897d-2320977cfe01 | 192.168.32.20 | nova | 163 | | 192.168.68.239 | afde96f2-9bac-441a-a0c7-589ace2ac6b9 | 192.168.32.15 | nova | 164 | | 192.168.68.246 | 00ceedf4-8d85-4ea5-8f42-78a1ab521a62 | 192.168.32.13 | nova | 165 | | 192.168.68.250 | c1ef2314-6067-464d-85ec-de2a26a80f3e | 192.168.32.4 | nova | 166 | | 10.3.4.1 | 192dadcc-e786-4366-8091-2e9a364a65cf | 192.168.32.17 | nova | 167 | +----------------+--------------------------------------+---------------+------+ 168 | $ nova add-floating-ip docker-internal 192.168.68.236 169 | 170 | Wait a couple seconds, and set up your domain registrar to map the subdomain docker-internal to this IP address. After that, run: 171 | 172 | 等一小会儿,并把子域名 docker-internal 绑定到当前的 IP,然后用 SSH 登陆: 173 | 174 | $ ssh ubuntu@docker-internal.example.com 175 | 176 | 177 | Hooray! 178 | 179 | 哦耶!搞定! 180 | 181 | ###Deploy and configure the registry 182 | ###部署和配置 registry 183 | 184 | Now that we have our server, let's install some packages to get started. 185 | 186 | 我们已经有自己的服务器了,下面我们来装几个必要软件吧。 187 | 188 | # 安装软件之前,我们先更新一下软件源列表,然后重启 189 | ubuntu@docker-internal:~$ sudo apt-get update 190 | ubuntu@docker-internal:~$ sudo apt-get upgrade 191 | ubuntu@docker-internal:~$ sudo reboot now 192 | 193 | #登陆到docker registry 194 | $ ssh ubuntu@docker-internal.example.com 195 | 196 | # 切换到root用户 197 | ubuntu@docker-internal:~$ sudo su 198 | 199 | # 安装nginx-extras包,我们要用其中的chunkin模块 200 | root@docker-internal:~# apt-get install git nginx-extras 201 | 202 | # 安装apache2-utils包,这样我们就可以用htpasswd命令来设置密码 203 | root@docker-internal:~# apt-get install apache2-utils 204 | 205 | # 安装一些必要的依赖 206 | root@docker-internal:~# apt-get install build-essential libevent-dev libssl-dev liblzma-dev python-dev python-pip 207 | 208 | # 安装redis来实现我们的LRU缓存策略 209 | root@docker-internal:~# apt-get install redis-server 210 | root@docker-internal:~# apt-get clean 211 | 212 | Now that we have that out of the way, let's install the docker registry: 213 | 214 | 必要的软件都装好了,下面我们就来安装 docker registry: 215 | 216 | root@docker-internal:~# git clone https://github.com/dotcloud/docker-registry.git /opt/docker-registry 217 | root@docker-internal:~# cd /opt/docker-registry 218 | 219 | # 切换到最新的 registry 版本 220 | root@docker-internal:~# git checkout 0.6.3 221 | 222 | # 创建日志路径 223 | root@docker-internal:~# mkdir -p /var/log/docker-registry 224 | 225 | # 安装 pip 包 226 | root@docker-internal:~# pip install -r requirements.txt 227 | root@docker-internal:~# cp config/config_sample.yml 228 | 229 | ***这里作者没有指定要拷贝到哪里*** 230 | 231 | If you've done this all correctly, we should now be able to test the registry will run with: 232 | 233 | 如果一切顺利,我们现在应该可以用下面的命令来测试一下 docker registry 了: 234 | 235 | root@docker-internal:~# ./wsgi.py 236 | 2014-01-13 23:38:38,470 INFO: * Running on http://0.0.0.0:5000/ 237 | 2014-01-13 23:38:38,470 INFO: * Restarting with reloader 238 | 239 | If you see this, you're doing great! Now, we just need to set up a couple more things. Remember that volume we mapped to this server earlier? Let's set that up now: 240 | 241 | 如果你看到的结果和上面一样,那么,恭喜你,成功了!接下来我们需要设置一些选项,记得我们之前分配给 docker registry 的分区吗?现在我们就来挂在这个分区: 242 | 243 | root@docker-internal:~# mkdir -p /data/registry 244 | root@docker-internal:~# mkfs.ext4 /dev/vdb 245 | root@docker-internal:~# mount /dev/vdb /data/registry 246 | 247 | And now, let's edit our configuration file for the docker registry. You can use http://uuidgenerator.net/ to generate a secret key: 248 | 249 | 现在,我们来编辑 docker registry 的配置文件,我们用 http://uuidgenerator.net 在线生成密钥: 250 | 251 | root@docker-internal:~# cat << EOF > /opt/docker-registry/config/config.yml 252 | # The 'common' part is automatically included (and possibly overriden by 253 | # all other flavors) 254 | common: 255 | # Set a random string here 256 | secret_key: REPLACEME 257 | standalone: true 258 | # This is the default configuration when no flavor is specified 259 | dev: 260 | storage: local 261 | storage_path: /tmp/registry 262 | loglevel: debug 263 | # To specify another flavor, set the environment variable SETTINGS_FLAVOR 264 | # $ export SETTINGS_FLAVOR=prod 265 | prod: 266 | storage: local 267 | storage_path: /data/registry 268 | loglevel: info 269 | # Enabling LRU cache for small files. This speeds up read/write on 270 | # small files when using a remote storage backend (like S3). 271 | cache: 272 | host: localhost 273 | port: 6379 274 | cache_lru: 275 | host: localhost 276 | port: 6379 277 | EOF 278 | 279 | Once this is done, set up an upstart job for the registry: 280 | 281 | 然后为 docker registry 设置一个 upstart 作业: 282 | 283 | root@docker-internal:~# cat << EOF > /etc/init/docker-registry.conf 284 | description "Docker Registry" 285 | version "0.6.3" 286 | author "Docker, Inc." 287 | 288 | start on runlevel [2345] 289 | stop on runlevel [016] 290 | 291 | respawn 292 | respawn limit 10 5 293 | 294 | # set environment variables 295 | env REGISTRY_HOME=/opt/docker-registry 296 | env SETTINGS_FLAVOR=prod 297 | 298 | script 299 | cd $REGISTRY_HOME 300 | exec gunicorn -k gevent --max-requests 100 --graceful-timeout 3600 -t 3600 -b 0.0.0.0:5000 -w 8 --access-logfile /var/log/docker-registry/access.log --error-logfile /var/log/docker-registry/server.log wsgi:application 301 | end script 302 | EOF 303 | 304 | And then start it with: 305 | 306 | 用下面的命令启动 registry 的作业: 307 | 308 | root@docker-internal:~# start docker-registry 309 | docker-registry start/running, process 10872 310 | 311 | Verify that it's running by checking: 312 | 313 | 用下面的命令检查 registry 的作业是否运行: 314 | 315 | root@docker-internal:~# cat /var/log/docker-registry/server.log 316 | 2014-01-14 00:33:44 [15051] [INFO] Starting gunicorn 18.0 317 | 2014-01-14 00:33:44 [15051] [INFO] Listening at: http://0.0.0.0:5000 (15051) 318 | 2014-01-14 00:33:44 [15051] [INFO] Using worker: gevent 319 | 2014-01-14 00:33:44 [15056] [INFO] Booting worker with pid: 15056 320 | 2014-01-14 00:33:44 [15057] [INFO] Booting worker with pid: 15057 321 | 2014-01-14 00:33:44 [15062] [INFO] Booting worker with pid: 15062 322 | 2014-01-14 00:33:45 [15067] [INFO] Booting worker with pid: 15067 323 | 2014-01-14 00:33:45 [15068] [INFO] Booting worker with pid: 15068 324 | 2014-01-14 00:33:45 [15069] [INFO] Booting worker with pid: 15069 325 | 2014-01-14 00:33:45 [15070] [INFO] Booting worker with pid: 15070 326 | 2014-01-14 00:33:45 [15071] [INFO] Booting worker with pid: 15071 327 | 328 | Now for nginx: 329 | 330 | 接下来,我们设置 nginx: 331 | 332 | root@docker-internal:~# rm /etc/nginx/sites-enabled/default 333 | root@docker-internal:~# cat << EOF > /etc/nginx/sites-enabled/docker-registry 334 | ` nginx的配置:` 335 | 336 | upstream docker-registry { 337 | server localhost:5000; 338 | } 339 | 340 | server { 341 | listen 443; 342 | server_name docker-internal.example.com; 343 | 344 | ssl on; 345 | ssl_certificate /etc/ssl/certs/docker-registry.crt; 346 | ssl_certificate_key /etc/ssl/private/docker-registry.key; 347 | 348 | proxy_set_header Host $http_host; # required for docker client's sake 349 | proxy_set_header X-Real-IP $remote_addr; # pass on real client's IP 350 | proxy_set_header Authorization ""; # see https://github.com/dotcloud/docker-registry/issues/170 351 | 352 | client_max_body_size 0; # disable any limits to avoid HTTP 413 for large image uploads 353 | 354 | # required to avoid HTTP 411: see Issue #1486 (https://github.com/dotcloud/docker/issues/1486) 355 | chunkin on; 356 | error_page 411 = @my_411_error; 357 | location @my_411_error { 358 | chunkin_resume; 359 | } 360 | 361 | location / { 362 | auth_basic "Restricted"; 363 | auth_basic_user_file docker-registry.htpasswd; 364 | 365 | proxy_pass http://docker-registry; 366 | proxy_set_header Host $host; 367 | proxy_read_timeout 900; 368 | } 369 | 370 | location /_ping { 371 | auth_basic off; 372 | proxy_pass http://docker-registry; 373 | } 374 | 375 | location /v1/_ping { 376 | auth_basic off; 377 | proxy_pass http://docker-registry; 378 | } 379 | } 380 | EOF 381 | ` ` 382 | 383 | root@docker-internal:~# service nginx restart 384 | 385 | And the associated htpasswd file (ensuring to replace USERNAME and PASSWORD): 386 | 387 | 别忘了在 htpasswd 文件里设置账号密码: 388 | 389 | root@docker-internal:~# htpasswd -bc /etc/nginx/docker-registry.htpasswd USERNAME PASSWORD 390 | 391 | 392 | Let's install an SSL key onto the server. In this example, I am assuming that someone has handed you an SSL key that has been signed and verified by a certificate authority. This SSL key could be for either 'docker-internal.example.com' or '*.example.com': 393 | 394 | 我们还要在服务器上安装一个 SSL 密钥。本例中,假设我们已经有认证机构颁发的 SSL证 书了,SSL 授权给'docker-internal.example.com'或者'*.example.com',用下面的命令来安装 SSL 密钥: 395 | 396 | root@docker-internal:~# mv server.key /etc/ssl/private/docker-registry.key 397 | root@docker-internal:~# mv server.crt /etc/ssl/certs/docker-registry.crt 398 | 399 | If you don't have the cash to fork out for a new SSL key, or you are just testing out this process before deploying, you can install a self-signed SSL key by following the instructions from Akadia: 400 | 401 | 如果你不打算花钱去搞一个认证机构授权的SSL密钥,或者你只是练习着部署 docker registry,那么你也可以按照 [Akadia的教程](http://www.akadia.com/services/ssh_test_certificate.html) 装一个自己授权的 SSL key,如下: 402 | 403 | root@docker-internal:~# openssl genrsa -des3 -out server.key 1024 404 | root@docker-internal:~# openssl req -new -key server.key -out server.csr 405 | root@docker-internal:~# cp server.key server.key.org 406 | root@docker-internal:~# openssl rsa -in server.key.org -out server.key 407 | root@docker-internal:~# openssl x509 -req -days 3650 -in server.csr -signkey server.key -out server.crt 408 | 409 | Please note that using self-signed certificates is currently waiting on pull request #2687. You will have to sit tight until it is merged into master, or you can try building Docker from source. 410 | 411 | 请注意,现在官方的 docker 还不能用自授权的证书,要等到 [`#2687`](https://github.com/dotcloud/docker/pull/2687) 的 pull request 合并到官方 master 分支后才能使用。或者,你也可以试着修改 docker 的源代码来让它支持自授权证书。 412 | 413 | ###Verification 414 | ###测试 415 | 416 | Finally, let's test this: 417 | 418 | 最后,我们来测试一下自己的 docker registry: 419 | 420 | root@docker-internal:~# exit 421 | ubuntu@docker-internal:~$ exit 422 | $ curl -u bacongobbler:******* https://docker-internal.example.com 423 | "docker-registry server (prod)" 424 | $ docker login https://docker-internal.example.com 425 | Login against server at https://docker-internal.example.com/v1/ 426 | Username (): bacongobbler 427 | Login Succeeded 428 | $ docker pull busybox 429 | Pulling repository busybox 430 | e9aa60c60128: Download complete 431 | $ docker tag busybox docker-internal.example.com/busybox 432 | $ docker push docker-internal.example.com/busybox 433 | The push refers to a repository [docker-internal.example.com/busybox] (len: 1) 434 | Sending image list 435 | Pushing repository docker-internal.example.com/busybox (1 tags) 436 | Pushing tags for rev [e9aa60c60128] on {https://docker-internal.example.com/v1/repositories/busybox/tags/latest} 437 | e9aa60c60128: Image already pushed, skipping 438 | 439 | And we're done! One docker registry, deployed on Openstack and ready to go. 440 | 441 | 完成!现在我们在 Openstack 上部署了一个 docker registry,随时可用! 442 | 443 | ###What's Next? 444 | ###下一步 445 | 446 | So, after deploying the registry, what are some things that we can do to improve or enhance this project? I can think of a couple: 447 | 448 | 部署好 docker registry 后,我们还可以进一步让它跑的更好,比如: 449 | 450 | - set up email notifications on registry exceptions 451 | - ship the logs off to logstash or some other log aggregation tool 452 | - deploy the registry on CentOS or RHEL 453 | - do some benchmarking to see how well the registry scales 454 | 455 | - 当docker registry崩溃的时候,发出邮件通知 456 | - 用[logstash](http://logstash.net/)或其他日志软件来管理日志 457 | - 把docker registry部署到CentOS或者RHEL 458 | - 做一些测试,看看docker registry的性能如何 459 | 460 | What other suggestions can you think of? Leave a comment below! 461 | 462 | 这只是我想到的一些,如果你有什么好点子,请在下面留言! 463 | 464 | Here at ActiveState, we're proud to say that we are actively using the Docker project in Stackato v3. If you missed Phil's amazing post on everything that's in Stackato v3, please take a look at his post, as well as the section about where Docker fits in with Stackato. 465 | 466 | 在 ActiveState,我们在 [Stackato v3](http://www.activestate.com/stackato) 项目中大量的使用了 Docker。Phil 在博客中全面的介绍了 Stackat v3,如果你还没来得及看,一定要去拜读他的 [大作](http://www.activestate.com/blog/2013/11/technical-look-stackato-v30-beta) ,特别是其中 [Stackato在哪些地方适合用Docker](http://www.activestate.com/blog/2013/11/technical-look-stackato-v30-beta#docker) 这一节。 467 | 468 | 图片来自:[Glyn Lowe Photoworks](http://www.flickr.com/photos/glynlowe/) 469 | 470 | 471 | 472 | 473 | [1]: http://www.activestate.com/sites/default/files/images/blog/ship-with-containers.jpg 474 | -------------------------------------------------------------------------------- /lance.md: -------------------------------------------------------------------------------- 1 | ##Lance Ju 2 | -------------------------------------------------------------------------------- /meaglith.md: -------------------------------------------------------------------------------- 1 | ##Meaglith Ma 2 | -------------------------------------------------------------------------------- /quickly-ssh-into-a-docker-container.md: -------------------------------------------------------------------------------- 1 | #Quickly SSH into a Docker container 2 | #如何用SSH快速登录Docker容器 3 | 4 | I’ve been playing around with Docker for a few months and it’s great. 5 | 玩了几个月的[Docker](https://www.docker.io/),发现这东西实在太棒了! 6 | 7 | One thing that is slightly rage-inducing when using docker is having to SSH into a container. Generally if you have multiple containers that run sshd, you’ll want the SSH ports to be generated randomly to prevent conflicts. Connecting via SSH is slightly tedious to do in this case, as there are several steps involved. 8 | 但是Docker有时令人有点儿抓狂,那就是每次使用Docker,都必须通过SSH登陆到Docker容器中。一般来说,如果你有多个容器都在跑sshd,就得让SSH随机生成端口号以防止端口冲突。用SSH登陆着实需要几个步骤,在多个SSH一起跑的时候,就显得有些繁琐了。 9 | 10 | 11 | ###Problem 12 | ###问题 13 | *** 14 | 15 | Basically the routine is to run docker ps: 16 | 17 | 用SSH登陆的基本思路就是使用`docker ps`: 18 | 19 | 20 | CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 21 | e53a722096f0 aafd21071b99 /opt/bin/run_all 41 minutes ago Up 28 minutes 127.0.0.1:49251->22/tcp, 127.0.0.1:49252->9200/tcp es-b 22 | 0208431f9c7b aafd21071b99 /opt/bin/run_all 41 minutes ago Up 28 minutes 127.0.0.1:49249->22/tcp, 127.0.0.1:49250->9200/tcp es-a 23 | 24 | If you scroll to the right of that you’ll see the randomly generated port in the PORTS column: 25 | 以上即是docker ps的输出结果,在最右面的PORTS这一列,可以看到随机生成的端口号: 26 | 27 | 127.0.0.1:49251->22/tcp 28 | 29 | 30 | The next step is to type out the SSH command. You can either give in to RSI by copying the port with the mouse, or type it out: 31 | 接下来就是输入SSH命令,可以用鼠标复制端口号,或者直接输入端口号: 32 | 33 | ssh root@localhost -p 49251 34 | 35 | I think that’s too much work to simply SSH into a container! 36 | 仅仅是通过SSH登录容器而已,这也太麻烦了! 37 | 38 | ###Solution 39 | *** 40 | 41 | 42 | I gave into annoyance and wrote a straightforward Python script to automatically do this for me. The Python script is calleddssh. It runs docker inspect, grabs the port, then runs SSH for you: 43 | 我怒了!于是我写了个Python脚本来解决问题。Python脚本叫做`dssh`,脚本里面先执行`docker inspect`,然后从结果中取出端口,然后再调用SSH登录容器: 44 | 45 | #!/usr/bin/env python 46 | import sys 47 | import subprocess 48 | import json 49 | 50 | cmd = 'sudo docker inspect {}'.format(sys.argv[1]) 51 | output = subprocess.check_output(cmd, shell=True).decode('utf-8') 52 | data = json.loads(output) 53 | 54 | port = data[0]['NetworkSettings']['Ports']['22/tcp'][0]['HostPort'] 55 | 56 | cmd = 'ssh root@localhost -p {}'.format(port) 57 | subprocess.call(cmd, shell=True) 58 | 59 | You might notice it makes some assumptions which will crash the script if they’re not followed. There needs to be an argument for the container ID or name. In the example above I could use either "e53a722096f0" or "es-b" as the argument. There also has to be an sshd process port listening on 22, and a configured container to forward that port. 60 | 也许你注意到了,这个脚本中我们假设的一些条件如果不满足,脚本就会崩溃。我们需要一个参数来表示容器的ID或者名称。咱上面的例子中我可以指定参数为"e53a722096f0"或者"es-b"。同时还必须有一个sshd进程监听22端口,还要配置一个容器来转发22端口。 61 | 62 | The output of docker inspect is a handy JSON string coming straight from the Docker Remote API. This in turn gives us the port we need. We then simply run subprocess.call and suddenly you’re in the container. 63 | `docker inspect`命令的结果是由[Docker Remote API](http://docs.docker.io/en/latest/api/docker_remote_api_v1.8/#inspect-a-container)输出的简单易读的JSON字符串,结果中也返回来我们需要的端口号。有了端口号,我们只需要调用`subprocess.call`来执行SSH命令,然后瞬间登陆到容器。 64 | 65 | 66 | ###Closing 67 | ###结束语 68 | *** 69 | I did attempt this not long ago but failed. The attempt was to use docker-py but unfortunately it seemed to need root, which I couldn’t work a way to avoid it. I needed to SSH into docker as my non-privileged user because of SSH keys, so instead I made it print out the SSH command for it to be executed, but it was a cumbersome solution. 70 | 不久之前,我试了这个方法,但是没成功。方法中使用了[`docker-py`](https://github.com/dotcloud/docker-py),必须用root权限才能执行,所以我只能用非root用户来登陆Docker容器。所以我在脚本中把SSH命令打印出来执行,但是这样做显得太笨拙了。 71 | 72 | 73 | If you want the latest version, it’ll be updated in my dotfiles repository on github. 74 | 请去我Github上的[dotfiles仓库](https://github.com/gak/dotfiles/blob/master/home/bin/dssh)查看最新的脚本。 75 | 分类:Hacking,标签:docker, python, ssh 76 | 2014年2月2日 77 | Gerald Kaszuba. 78 | 79 | This entry was posted in Hacking and tagged docker, python, ssh on January 2, 2014 by Gerald Kaszuba. -------------------------------------------------------------------------------- /rocker.md: -------------------------------------------------------------------------------- 1 | ##Rocker Lee 2 | -------------------------------------------------------------------------------- /the-docker-book-sample-download.md: -------------------------------------------------------------------------------- 1 | [James Turnbull](http://www.jamesturnbull.net) 写了 [七本](http://www.amazon.com/James-Turnbull/e/B002BLLCPI) 关于开源的技术书籍。最近他正在编写一本关于 [Docker](http://docker.io) 技术的 [书籍](http://www.dockerbook.com),计划在 [Docker](http://docker.io) 1.0 版本发布的时候同时发表。 2 | [James Turnbull](http://www.jamesturnbull.net) 是 [Docker](http://docker.com) 的副总裁,是 [Docker](http://docker.io) 的核心开发者之一,他的书一定是 [Docker](http://docker.io) 的权威指南。 3 | 4 | 目前已经有这本书的样章可以 [下载](http://docker.u.qiniudn.com/TheDockerBook_sample.pdf),大家可以提前阅摘要,我们会在本书发布时组织社区进行翻译,最快为大家带来中文版本。如果您有意参与翻译的工作,可以联系我们:meaglith.ma@aliyun.com。 5 | --------------------------------------------------------------------------------