Docker 初体验

引言

前段时间在Udacity上学习Hadoop, 视频教程中提到了使用CDH(cloudera distribution for hadoop)来搭建实验环境,我就到CDH官网试水,发现有一种使用Docker镜像的方式,由于我机器资源有限,最终也没能搭建起Hadoop实验环境,不过从这个地方开始接触了Docker的使用,发现一片新的天地,才体会到为啥好多人都说Docker是DevOps神器了。

体验Docker

国内解决pull镜像慢的问题

DaoCloud加速器配置:

申请DaoCloud帐号, 登录并进入控制台, 控制台上方点击进入加速器,进入配置加速器页面,根据不同平台自行选择方案

我使用MacOS,所以如下图:

Docker Daemon程序中的设置如下图所示:

如此配置以后,你在国内可以避免龟速拉取镜像的问题。此内业界良心。

国内解决push镜像慢的问题

由于上传镜像到Docker Hub没有什么别的办法,国内直接push的速度简直无法容忍,虽然可以使用DaoCloud的镜像仓库功能,不过那个需要收费,这不符合我这穷屌的身份,所以,我们可以考虑本地导出镜像文件,上传到网盘,下载下来,再导入其它机器的本地Docker环境中即可。虽然有些麻烦,不过不收费啊!这个push的问题解决思路也有了。

我准备和git仓库联合一起使用就可以共享了,因为我自己电脑上搭了个gogs服务, 而且家里服务器开着花生壳DDNS服务,所以自己可以方便的来回传送。

  • 这个是导出docker镜像的方法:

1docker save -o image_file_path docker_local_image 2
  • 中间是你把导出的镜像上传到任意你觉得共享方便的位置,例如上传网盘或者推到git仓库中,方便共享。

  • 最后是导入docker镜像文件到本地docker环境:

1docker load --input image_file_path 2

大功告成,导入后可以使用docker images命令确认一下。

Docker 实际的应用 Docker 下创建Ubuntu16.04 下的swift语言学习环境

swift的官方镜像已经在Docker Hub上能够搜索到了,详细的使用说明也在镜像的详情描述中,很方便学习和实验。 不过重复造个小轮子的过程我还是想要体会一下。

假设你已经安装了docker daemon,并已经后台运行,而且在国内也已经配置好了DaoCloud的加速器,那么在终端下使用命令拉下ubuntu的官方镜像先,我们就是基于这个基础镜像来设定我们自己的开发环境的:

1docker pull ubuntu 2

当然如果你想要查找镜像时可以使用docker search ubuntu 命令,这个用法与apt-cache search [target]流程很相似。

镜像拉取成功后就可以使用docker images列出当前我们拉取到本地的所有镜像:

1bogon:~ JokerAtBaoFeng$ docker images 2REPOSITORY TAG IMAGE ID CREATED SIZE 3ubuntu latest f49eec89601e 3 weeks ago 129 MB 4

此时的镜像的角色相当于面向对象程序设计中的类一样,需要实例化后使用,对象实例化过程对应的就是从docker镜像文件创建一个容器的过程,如果把docker镜像当作一个类的话,容器就相当于从类生成的一个对象,容器的任何改变不会影响到原始的docker镜像,我们可以修改容器,并把修改后的容器保存为另一个镜像,这就是生成定制镜像的思路。

那么,我们以交互式控制台方式创建并运行ubuntu的一个容器,并进入bash,其中-it意思是以交互式(interactive)终端(tty)的方式运行,--name=swift-ubuntu指定容器的名称,/bin/bash是容器启动后执行的命令,也就是进入bash控制台:

1docker run -it --name=swift-ubuntu ubuntu /bin/bash 2

运行成功后会进入:

1root@708cefae82b7:/# 2

默认是root用户,这里我们使用诸如apt-get命令时就不需要sudo了。

官方的镜像是最小的,只有129M,我们首先要更新和升级系统到最新,加个-y参数,以使更新过程不中断,不提示用户确认是否安装相应的包,默认用户同意安装:

1apt-get update && apt-get upgrade -y 2

系统升级之后,我们就可以安装swift的REPL环境了,这个可以参考官网安装说明:

安装依赖

1 apt-get install -y clang libicu-dev 2

这里是安装clang编译器相关工具和运行swift REPL运行库依赖。

下载swift编译包swift-<VERSION>-<PLATFORM>.tar.gz
你可以直接在容器中使用wget下载,或者在PC上下载下来后再拷贝到容器中:

容器内下载

1apt-get install wget -y && cd /opt/ && wget https://swift.org/builds/swift-3.0.2-release/ubuntu1604/swift-3.0.2-RELEASE/swift-3.0.2-RELEASE-ubuntu16.04.tar.gz 2

我们把文件下载到/opt/目录下。

将PC上的文件拷贝到容器中

这里的命令不是在容器窗口中运行,而是在宿主机的控制台运行。

1docker cp swift-3.0.2-RELEASE-ubuntu16.04.tar.gz swift-ubuntu:/opt/ 2

swift-ubuntu是之前创建运行容器时指定的容器名称,我们把PC上的swift编译包拷贝到容器的/opt/目录下。

当然这个命令也可以把容器中指定目录中的文件,拷贝到宿主机上,只要docker cp之后的两个地址的位置对调一下就可以了。

准备就绪,开始配置swift REPL环境

在/opt/目录下新建一个目录swift,并把刚才下载的编译包移进去,并解压:

1mkdir -p /opt/swift && 2mv /opt/swift-*-RELEASE-ubuntu*.tar.gz /opt/swift && 3cd /opt/swift && 4tar zxvf swift-*-RELEASE-ubuntu*.tar.gz 5

制作swift目录的符号链接,这样版本更新时,只要重新生成对应的符号链接就可以轻松升级:

1ln -s /opt/swift/swift-*-RELEASE-ubuntu*[0-9] /opt/swift/swift-current 2

下一步,进行添加用户环境变量。配置到~/.bashrc并使生效,我们调用swift二进制文件就是在刚才解压后的目录中的/usr/bin下面,只不过我们通过符号链接的方式进行访问目录:

1echo "export PATH=/opt/swift/swift-current/usr/bin:${PATH}" >> ~/.bashrc && source ~/.bashrc 2

现在,你可以在容器中运行swift --version来确认环境变量是否配置成功,我的结果显示如下:

1root@708cefae82b7:/opt/swift# swift --version 2Swift version 3.0.2 (swift-3.0.2-RELEASE) 3Target: x86_64-unknown-linux-gnu 4

这就说明环境变量配置成功了。

但我们运行一个swfit命令会发现有一些依赖需要另外安装,主要是libpython2.7.so.1.0

1root@708cefae82b7:/opt/swift# swift 2/opt/swift/swift-3.0.2-RELEASE-ubuntu16.04/usr/bin/lldb: error while loading shared libraries: libpython2.7.so.1.0: cannot open shared object file: No such file or directory 3

安装依赖:

1root@708cefae82b7:/opt/swift# apt-get install -y libpython2.7 2

再运行:

1root@708cefae82b7:/opt/swift# swift 2/opt/swift/swift-3.0.2-RELEASE-ubuntu16.04/usr/bin/lldb: error while loading shared libraries: libxml2.so.2: cannot open shared object file: No such file or directory 3 4

发现还缺少libxml2.so.2,安装之:

1apt-get install -y libxml2 2

再运行,发现:

1root@708cefae82b7:/opt/swift# swift 2error: failed to launch REPL process: process launch failed: 'A' packet returned an error: 8 3

这是由于容器运行的默认特性不支持swift REPL导致的,初次遇到时,怀疑自己的配置有问题,不过参看了docker hub的官方说明,如下使用方式:

所以我们先退出当前容器,把我们目前的容器生成一个新的镜像,从新镜像重新启动,并使用官方docker image的运行参数:

退出当前容器

1root@708cefae82b7:/opt/swift# exit 2exit 3查看容器状态 4joker@localhost:~ $ docker ps -a 5CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 6708cefae82b7 ubuntu "/bin/bash" About an hour ago Exited (0) 6 seconds ago swift-ubuntu 7

这时我们的容器已经成为Exited状态。

从容器生成docker镜像

这很类似git的方式,相当于在基础镜像ubuntu的基础上,变动一次,commit 就是在基础镜像上加一层变动层(layer),相当于git diff的输出内容一样,合并基础镜像和变动层就可以生成一个新的定制镜像。

1joker@localhost:~ $ docker commit swift-ubuntu yourhubname/swift-ubuntu 2sha256:387fc3cb1d8e8c53ba15e1e343d9a4f71550780f2812d08c2eaaf264b8a9709d 3

查看生成的新镜像

可以看到现在的镜像就很大了,有1G+。

1joker@localhost:~ $ docker images 2REPOSITORY TAG IMAGE ID CREATED SIZE 3yourhubname/swift-ubuntu latest 387fc3cb1d8e About a minute ago 1.17 GB 4ubuntu latest f49eec89601e 5 weeks ago 129 MB 5

重新创建基于yourhubname/swift-ubuntu镜像的新容器

运行时,添加了--cap-add sys_ptrace选项,这可能和调试打断点需要系统权限有关,导致我们之前没有成功启动swift REPL环境,这个我没有深究。

1joker@localhost:~ $ docker run -it --cap-add sys_ptrace yourhubname/swift-ubuntu /bin/bash 2root@24a26d4b854d:/# swift 3Welcome to Swift version 3.0.2 (swift-3.0.2-RELEASE). Type :help for assistance. 4 1> 5

好了,出现这个就说明swift的REPL环境搭好了,这个类似于python的交互环境。退出swift REPL环境使用:quit命令。 ;-)

配置后的清理工作

退出了容器环境后使用docker ps -a发现有两个容器,把之前那个旧容器删掉。

1joker@localhost:~ $ docker ps -a 2CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 324a26d4b854d yourhubname/swift-ubuntu "/bin/bash" 11 minutes ago Exited (0) 19 seconds ago happy_babbage 4708cefae82b7 ubuntu "/bin/bash" About an hour ago Exited (0) 33 minutes ago swift-ubuntu 5

删掉旧容器:

1joker@localhost:~ $ docker rm swift-ubuntu 2swift-ubuntu 3

现在你已经有了新镜像yourhubname/swift-ubuntu,当然也可以把基础镜像ubuntu删除掉了

1joker@localhost:~ $ docker images 2REPOSITORY TAG IMAGE ID CREATED SIZE 3yourhubname/swift-ubuntu latest 387fc3cb1d8e 16 minutes ago 1.17 GB 4ubuntu latest f49eec89601e 5 weeks ago 129 MB 5

删掉基础镜像:

1joker@localhost:~ $ docker rmi ubuntu 2Untagged: ubuntu:latest 3Untagged: ubuntu@sha256:0c01b5105fc57b5eb8b7bb1d697b9dc5602022f69a0a33bf282b117e7a754a91 4

现在你就只有一个自己定制的镜像了,不过再次运行时,不要再使用docker run -it --cap-add sys_ptrace yourhubname/swift-ubuntu /bin/bash,因为它会创建新容器。因为你已经运行过一次了,容器已经创建成功,就可以直接从容器启动。如果你非要使用那条命令,加一个--rm选项,它会在创建新容器时,把已经存在的容器删掉:

查看所有容器状态:

1joker@localhost:~ $ docker ps -a 2CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 324a26d4b854d yourhubname/swift-ubuntu "/bin/bash" 16 minutes ago Exited (0) 5 minutes ago happy_babbage 4

启动已经生成的容器happy_babbage:

1joker@localhost:~ $ docker start happy_babbage 2happy_babbage 3

把容器挂接到交互终端,进入bash并打开swift REPL:

1joker@localhost:~ $ docker exec -it happy_babbage /bin/bash 2root@24a26d4b854d:/# swift 3Welcome to Swift version 3.0.2 (swift-3.0.2-RELEASE). Type :help for assistance. 4 1> 5

终于完工了,吃个鸡腿压压惊先。

后记

如果你对Linux下使用Swift编程感兴趣,可以阅读这部书Mastering Swift 3 - Linux,博主友情推荐。还有就是Docker的官方文档也可以作为镜像拉下来,本地运行jekyll服务阅读,有时网差时也可以这么干,用来进一步学习Docker:

1joker@localhost:~ $ docker run -p80:4000 docs/docker.github.io 2Docker docs are viewable at: 3http://0.0.0.0:4000 4

然后你本地浏览器输入http://localhost就可以阅读Docker文档了。

页面很舒服,这居然可以用jekyll做到,现在回头看看我的jekyll博客真的是像一坨屎一样 -_-#

本博文曾因为博主自己的傻B行为被覆盖编辑过一次,幸好有位少年拯救了在下,他提到了搜索引擎的网页快照功能(虽然最终不是由此寻回丢失的博文,是别家网站的爬虫把我博客爬走了-_-#),在此一并感谢之。

顺便把他挂在墙上

代码交流 2021