阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

利用Docker构建开发环境详解

118次阅读
没有评论

共计 14801 个字符,预计需要花费 38 分钟才能阅读完成。

最近接触 PAAS 相关的知识,在研发过程中开始使用 Docker 搭建了自己完整的开发环境,感觉生活在 PAAS 时代的程序员真是幸福,本文会简要介绍下 Docker 是什么,如何利用 Docker 来搭建自己的开发环境(本文主要是面向 Mac OS X),以及期间所遇到的一些坑和解决方案。(本文会要求你对 PAAS、LXC、CGroup、AUFS 有一定的了解基础,请自行 Google)

大背景–虚拟化技术历史

计算机虚拟化技术由来已久,从硬件仿真到全虚拟化,再到准虚拟化和操作系统虚拟化,各种技术粉墨登场,种类繁多,说实在的有点眼花缭乱和复杂;但用户的核心诉求一直是比较简单的,降低信息技术(IT)的运营成本,提高资源利用率,提高安全性和可靠性等等;虽说用户的核心诉求比较简单,但每个时代的需求场景却是不同的。在大型机时代,虚拟化技术被用来支持多个用户能够同时使用大型机,在 x86 架构时代,随着企业服务的大规模部署,虚拟化技术主要是用来提高企业资源的利用率,而现如今,随着云计算时代的到来,人们对应用的安全性、隔离性越来越高,对于部署的标准化以及虚拟机的性能要求越来越高。现如今,一种叫 Linux 容器的虚拟化技术逐渐得到广泛的应用,它的优点有许多,本文不一一赘述,有太多的文章可以参考。

什么是 Docker?

docker 的英文本意是码头工人,也就是搬运工,这种搬运工搬运的是集装箱(Container),集装箱里面装的可不是商品货物,而是任意类型的 App,Docker 把 App(叫 Payload)装在 Container 内,通过 Linux Container 技术的包装将 App 变成一种标准化的、可移植的、自管理的组件,这种组件可以在你的 latop 上开发、调试、运行,最终非常方便和一致地运行在 production 环境下。

Docker 的核心底层技术是 LXC(Linux Container),Docker 在其上面加了薄薄的一层,添加了许多有用的功能。这篇 stackoverflow 上的问题和答案很好地诠释了 Docker 和 LXC 的区别,能够让你更好的了解什么是 Docker,简单翻译下就是以下几点:

  • Docker 提供了一种可移植的配置标准化机制,允许你一致性地在不同的机器上运行同一个 Container;而 LXC 本身可能因为不同机器的不同配置而无法方便地移植运行;
  • Docker 以 App 为中心,为应用的部署做了很多优化,而 LXC 的帮助脚本主要是聚焦于如何机器启动地更快和耗更少的内存;
  • Docker 为 App 提供了一种自动化构建机制(Dockerfile),包括打包,基础设施依赖管理和安装等等;
  • Docker 提供了一种类似 git 的 Container 版本化的机制,允许你对你创建过的容器进行版本管理,依靠这种机制,你还可以下载别人创建的 Container,甚至像 git 那样进行合并;
  • Docker Container 是可重用的,依赖于版本化机制,你很容易重用别人的 Container(叫 Image),作为基础版本进行扩展;
  • Docker Container 是可共享的,有点类似 github 一样,Docker 有自己的 INDEX,你可以创建自己的 Docker 用户并上传和下载 Docker Image;
  • Docker 提供了很多的工具链,形成了一个生态系统;这些工具的目标是自动化、个性化和集成化,包括对 PAAS 平台的支持等;

那么 Docker 有什么用呢?对于运维来说,Docker 提供了一种可移植的标准化部署过程,使得规模化、自动化、异构化的部署成为可能甚至是轻松简单的事情;而对于开发者来说,Docker 提供了一种开发环境的管理方法,包括映像、构建、共享等功能,而后者是本文的主题。

Docker 的安装和构成

Docker 官方本身提供了非常具体的安装教程,这里不说具体的安装过程,请参考 Docker 安装(Mac 系统),重要的是描述下原理和安装完成后的结构,好对 Docker 更好的了解。由于 LXC 本身不支持 Mac 内核,因此需要跑一个 VirtualBox 虚拟机(TinyCoreLinux)来安装,幸好 Docker 社区提供了一个非常方便的工具 boot2docker(其实就是一个 VBoxManage 的包装 shell 脚本),用于安装 Mac 下的整个 Docker 环境。具体的结构如下:

利用 Docker 构建开发环境详解

如图所示,安装完成后,具体情况如下:

  • 在 Mac 的 home 目录~/.boot2docker 下创建了虚拟机所需要的文件,其中 boot2docker.iso 是虚拟机映像,这是一个由 CD-ROM 引导的 TinyCoreLinux 系统;而 boot2docker-vm.vmdk 文件则是你的虚拟机磁盘,你所有的持久化数据都存放在这里,包括 docker 创建的 lxc 容器等文件。
  • 在 Mac 下,docker 被分为客户端 docker-client 和服务端 docker-daemon 两部分,如果是在 linux(比如 Ubuntu),实际上则是同一个可执行文件同时充当客户端和服务端。docker-daemon 可以监听 unix scoket,也可以在 tcp socket(默认端口为 4234),docker-client 会通过一个叫 DOCKER_HOST 的环境变量读取服务地址和端口,因此你应该在你的 bash_profile 文件里面添加这么一行:

export DOCKER_HOST=tcp://127.0.0.1:4243

docker-daemon 跑在虚拟机上,这个程序实际上就是接收 docker-client 发送过来的消息命令,创建、启动和销毁 lxc 容器,以及 docker 本身的版本管理、映像存储等等 运行你的第一个 docker 容器 安装完成后,就差不多可以开始创建和运行 docker 容器了,在这之前,你首先得下载一个 Image,什么是 Image?我们先来了解 docker 的 2 个基础概念:ImageContainer

Container 和 Image 在 Docker 的世界里,Image 是指一个只读的层(Layer),这里的层是 AUFS 里的概念,最直观的方式就是看一下 docker 官方给出的图:

利用 Docker 构建开发环境详解

Docker 使用了一种叫 AUFS 的文件系统,这种文件系统可以让你一层一层地叠加修改你的文件,最底下的文件系统是只读的,如果需要修改文件,AUFS 会增加一个可写的层(Layer),这样有很多好处,例如不同的 Container 可以共享底层的只读文件系统(同一个 Kernel),使得你可以跑 N 多个 Container 而不至于你的硬盘被挤爆了!这个只读的层就是 Image!而如你所看到的,一个可写的层就是 Container。

那 Image 和 Container 的区别是什么?很简单,他们的区别仅仅是一个是只读的层,一个是可写的层,你可以使用 docker commit 命令,将你的 Container 变成一个 Image,也就是提交你所运行的 Container 的修改内容,变成一个新的只读的 Image,这非常类似于 git commit 命令,感觉真棒!

实际上这就是 Docker 对 Container 映像的版本管理基石,AUFS 文件系统实在是太美妙了,更多细节可以参考 DotCloud 的这篇文章。

CentOS 6/ 7 系列安装 Docker http://www.linuxidc.com/Linux/2014-07/104768.htm

Docker 的搭建 Gitlab CI 全过程详解 http://www.linuxidc.com/Linux/2013-12/93537.htm

Docker 安装应用 (CentOS 6.5_x64) http://www.linuxidc.com/Linux/2014-07/104595.htm

Docker 和一个正常的虚拟机有何区别? http://www.linuxidc.com/Linux/2013-12/93740.htm

在 Docker 中使用 MySQL http://www.linuxidc.com/Linux/2014-01/95354.htm

Docker 将改变所有事情 http://www.linuxidc.com/Linux/2013-12/93998.htm

Docker 安装应用 (CentOS 6.5_x64) http://www.linuxidc.com/Linux/2014-07/104595.htm

Docker 是什么?让我来告诉你   http://www.linuxidc.com/Linux/2014-10/107967.htm

运行和退出

在了解了 Image 和 Container 的概念后,我们可以开始下载一个 Image,Docker 的好处就是提供了一个类似 github 的 Image 仓库管理,你可以非常方便 pull 别人的 Image 下来运行,例如,我们可以下载一个 ubuntu Image:

docker pull ubuntu:13.10

这里的 13.10 是一个 Tag,类似于 git 的 tag,这里的 tag 可以为你制定一个 ubuntu 的版本。下载完成后,执行 docker images 命令可以列出你已经下载或者自己构建的 image:(请允许我使用可爱的马赛克 :))

利用 Docker 构建开发环境详解

你可以看到 ubuntu:13.10 的大小为 178MB,以及它的 IMAGE ID。现在我们开始运行一个 Container,命令很简单,例如我们想运行一个执行 Shell 终端的 Container:

利用 Docker 构建开发环境详解

如你看到的,你已经进入到一个 Shell 里面,可以执行你想执行的任何命令,就和在 ubuntu 里面一样,进去后默认是在根目录 / 下,可以看到经典的 unix/linux 目录结构,以及你所运行的 bash 版本等信息。你可以给你的 Container 定一个名字,通过–name 选项,例如这里命名了 shell,日后你就可以直接用这个名字引用 Contanier。

退出一个 Container 也很简单,你直接 exit 就好了。其他更多的命令这里不做赘述,因为官方的文档已经非常全面,这里只是给一个直观的初步印象。下面进入主题。

更多详情见请继续阅读下一页的精彩内容 :http://www.linuxidc.com/Linux/2014-10/107969p2.htm

利用 Docker 搭建开发环境

我们先看看程序员在搭建开发环境时遇到的一些问题:

  • 软件安装麻烦 ,比如很多公司都使用 RedHat,一般开发人员又不给 root,安装一个 nginx 或者是 mysql 都得自己下载编译安装 权限问题,没有 root,一些软件无法运行,例如 dnsmasq;
  • 没有 root,无法修改 hosts,无法 netstat -nptl,无法 tcpdump,无法 iptable
  • 隔离性差 ,例如不同的开发人员如果在同一台主机环境下共享开发,虽然是用户隔离,但端口如果不规范可能会冲突;同一个 Mysql 如果权限管理不好很有可能误删别人的数据
  • 可移植性差 ,例如和生产环境不一致,开发人员之间也无法共享;更严重的情况是当有新人入职时,通常需要又折腾一遍开发环境,无法快速搭建

这些问题可以通过在本地搭建虚拟机来解决,但虚拟机是一个很笨重的解决方案,Docker 是一个非常轻量级的方案,而且还拥有虚拟机没有的一些功能,例如标准化 Image,Image 共享等,更重要的是,利用 Docker,你可以运行非常多的容器,在你的 Mac 下搭建一个分布式的开发环境根本不是什么大的问题,而且对内存、磁盘和 cpu 的消耗相比传统的虚拟机要低许多,这些都要归功于 AUFS 和 LXC 这两大神奇的技术。

构建基础 Image

想要搭建一个节省磁盘空间和扩展性良好的开发环境,最重要的第一步就是构建一个基础性的 Image,比如你的主要开发语言是 Ruby,那么你肯定需要一个已经安装好以下工具的基础 Image:

  • ruby
  • bundler
  • gem

然后在此基础上,你可以扩展这个基础的 Image(下面叫 base)为不同的开发环境,例如 rails,或者是 nats。当然,你的这个 base 也可以从别人的 Image 扩展而来,还记得我们刚刚 pull 下来的 Ubuntu:13.10 这个 Image 吗?你可以从这个 Image 扩展开始构建你的 base,如何做呢?Docker 提供了一种标准化的 DSL 方式,你只需要编写一个 Dockerfile,运行 docker build 指令,就可以构建你自己的 Image,这有点像 Makefile 和 make 命令一样,只是大家要构建的内容和构建语言不同。

Dockerfile 的语法请参考 Dockerfile Reference,这里给出上面提到的 Ruby 开发的 base Dockerfile 示例:

FROM ubuntu:13.10
RUN apt-get update
RUN apt-get install -y ruby ruby-dev gem
RUN gem install bundler

这里只用到了很简单的 2 个指令:FROM 和 RUN,FROM 指定了我们要扩展的 Image,RUN 指定我们要运行的命令,这里是安装 ruby,gem、bundler 等软件。写好 Dockerfile 后,运行以下指令就可以创建你的 base image 了:

docker build –rm -t dev:base .

-t 选项是你要构建的 base image 的 tag,就好比 ubuntu:13.10 一样 –rm 选项是告诉 Docker 在构建完成后删除临时的 Container,Dockerfile 的每一行指令都会创建一个临时的 Container,一般你是不需要这些临时生成的 Container 的 如你所想,我们可以像运行 ubuntu:13.10 那样运行我们的 base 了:

docker run -i -t –name ruby dev:base irb

这里我们使用 dev:base 这个 Image 运行了一个 irb 解释器(Ruby 的交互式解释器)。在构建完 base 之后,你可以依样画葫芦构建你的 rails 环境,很简单,只需要 FROM dev:base,然后 RUN 安装你的 rails 组件就可以了,不再赘述。最终你可能构建的开发环境是这样的:

利用 Docker 构建开发环境详解

如上图所示,base 和 service 都是从 ubutnu:13.10 继承而来,他们作为不同的基础开发环境,base 是 ruby 开发环境(也许命名为 dev:ruby 更为合适?),而 service 是一些基础数据服务,例如 mysql,memcache,我建议将这些第三方组件集中在一个 Container 中,因为他们的环境不经常修改,可以作为一种底层服务 Container 运行,除非你需要构建分布式的服务,例如 memcache 集群,那可以继续拆分。

指定 Image 入口

当你构建完你的 base Image 和其他应用的 Image 之后,你就可以启动这些 Image 了,还记得前面我们给出的运行命令吗?

docker run -i -t –name shell dev:base /bin/bash

这里我们运行了一个 bash,这样你就可以在 shell 里面执行你所想要执行的任何命令了,但是我们有时候并不想每次都启动一个 shell,接着再在 shell 里面启动我们的程序,比如一个 mysql,而是想一启动一个容器,mysql 服务就自动运行了,这很简单,Dockerfile 提供了 CMD 和 ENTRYPOINT 这 2 个指令,允许你指定一个 Image 启动时的默认命令。CMD 和 ENTRYPOINT 的区别是 CMD 的参数可以由 docker run 指令指定的参数覆盖,而 ENTRYPOINT 则不可以。例如我们想运行一个 memcached 服务,可以这么写 Dockerfile:

FROM ubuntu:13.10
RUN apt-get install -y memcached CMD memcached -u root -p 40000

或者可以这么写:

FROM ubuntu:13.10
RUN apt-get install -y memcached ENTRYPOINT [“memcached”, “-u”, “root”, “-p”, “40000”]

注意不要把 memcached 启动为后台进程,即加上 - d 选项,否则 docker 启动的 container 会马上 stop 掉,这点我也觉得比较意外。接着我们 build 这个 Image:

docker build -t dev:memcache .

这样,当你 build 完你的 Image 后,你可以直接将该 Image 运行为一个容器,它会自动启动 mysql 服务:

docker run –name memcache_service -d dev:memcache

注意使用 -d (detach) 选项,这样这个 container 就会作为后台进程运行了,接着你可以使用 docker ps 命令查看是否有在运行。

磁盘映射

大部分时候你会需要把你 host 主机(宿主)上的目录映射到 Container 里面,这样你就非常方便地在 host 主机上编辑代码,然后直接就可以在 Container 里面运行它们,而不用手动 copy 到 Container 里面再重启 Container。按理将 host 的目录映射到 guest(指 Container)上应该是一件很容易的事情,就好像 VMWare 那样,但可惜的是,由于 Mac 上的 Docker 多了一层虚拟机,因此多了一层周折,你必须先 VM 上的目录通过 sshfs mount 到 host(指 Mac)上,然后再将你的目录或文件 copy 到这个 mount 的目录,再将 VM 上的这个目录映射到 Container 里,听起来比较拗口,画个图会清晰很多。

利用 Docker 构建开发环境详解

如上图所示,VM 里面的 /mnt/sda1/dev/ 目录(你需要自己创建)通过 sshfs 命令 mount 到了 host 主机(Mac)的~/workspace/dev/ 目录,而 VM 里的 /mnt/sda1/dev/ 目录又被映射到了 Container 的 /src/ 目录下,这样你就可以在 Container 里面的 /src/ 目录下访问你的 host 文件了。具体如何做呢?首先你需要安装 sshfs 命令,然后将 VM 的 password 写到一个文件中,例如~/.boot2docker/b2d-passwd,在用 sshfs 命令 mount 起 VM 的 /mnt/sda1/dev 目录:

brew install sshfs
cat tcuser > ~/.boot2docker/b2d-passwd
sshfs docker@localhost:/mnt/sda1/dev ~/workspace/dev -p 2022 -o reconnect -o password_stdin < ~/.boot2docker/b2d-passwd

接着你在 run 一个 Container 的时候需要通过 - v 选项来将 /mnt/sda1/dev/ 映射到 /src 目录:

docker run -i -t dev:base -v /mnt/sda1/dev:/src /bin/bash

这样你就可以在你的 Container 的 /src 目录下看到你 host 里的文件了。磁盘映射还有 2 个地方需要注意:

  • 你的文件实际上是存储在 VM 里面的,也就是说你需要将你的目录或者文件 copy 到 VM 里面,你 sshfs 之后,就是 copy 到~/workspace/dev 目录下
  • 千万不要 sshfs mount 非 /mnt/sda1 下的目录,因为 VM 里面跑的是 TinyCoreLinux,这个 OS 的 rootfs 是临时性的(放在内存的,实际上就是 boot2docker.iso 文件里面的一个 rootfs),因此其根目录 / 下的东西(包括 /home)根本不会持久化,只有 /mnt/sda1 这个目录下的才能持久化。如果你放在 /home 目录下,只要 VM 一重启,就会丢失的,/mnt/sda1 则不会,实际上就是那个~/.boot2docker-vm.vmdk 文件挂载到了 /mnt/sda1 目录下

最近接触 PAAS 相关的知识,在研发过程中开始使用 Docker 搭建了自己完整的开发环境,感觉生活在 PAAS 时代的程序员真是幸福,本文会简要介绍下 Docker 是什么,如何利用 Docker 来搭建自己的开发环境(本文主要是面向 Mac OS X),以及期间所遇到的一些坑和解决方案。(本文会要求你对 PAAS、LXC、CGroup、AUFS 有一定的了解基础,请自行 Google)

大背景–虚拟化技术历史

计算机虚拟化技术由来已久,从硬件仿真到全虚拟化,再到准虚拟化和操作系统虚拟化,各种技术粉墨登场,种类繁多,说实在的有点眼花缭乱和复杂;但用户的核心诉求一直是比较简单的,降低信息技术(IT)的运营成本,提高资源利用率,提高安全性和可靠性等等;虽说用户的核心诉求比较简单,但每个时代的需求场景却是不同的。在大型机时代,虚拟化技术被用来支持多个用户能够同时使用大型机,在 x86 架构时代,随着企业服务的大规模部署,虚拟化技术主要是用来提高企业资源的利用率,而现如今,随着云计算时代的到来,人们对应用的安全性、隔离性越来越高,对于部署的标准化以及虚拟机的性能要求越来越高。现如今,一种叫 Linux 容器的虚拟化技术逐渐得到广泛的应用,它的优点有许多,本文不一一赘述,有太多的文章可以参考。

什么是 Docker?

docker 的英文本意是码头工人,也就是搬运工,这种搬运工搬运的是集装箱(Container),集装箱里面装的可不是商品货物,而是任意类型的 App,Docker 把 App(叫 Payload)装在 Container 内,通过 Linux Container 技术的包装将 App 变成一种标准化的、可移植的、自管理的组件,这种组件可以在你的 latop 上开发、调试、运行,最终非常方便和一致地运行在 production 环境下。

Docker 的核心底层技术是 LXC(Linux Container),Docker 在其上面加了薄薄的一层,添加了许多有用的功能。这篇 stackoverflow 上的问题和答案很好地诠释了 Docker 和 LXC 的区别,能够让你更好的了解什么是 Docker,简单翻译下就是以下几点:

  • Docker 提供了一种可移植的配置标准化机制,允许你一致性地在不同的机器上运行同一个 Container;而 LXC 本身可能因为不同机器的不同配置而无法方便地移植运行;
  • Docker 以 App 为中心,为应用的部署做了很多优化,而 LXC 的帮助脚本主要是聚焦于如何机器启动地更快和耗更少的内存;
  • Docker 为 App 提供了一种自动化构建机制(Dockerfile),包括打包,基础设施依赖管理和安装等等;
  • Docker 提供了一种类似 git 的 Container 版本化的机制,允许你对你创建过的容器进行版本管理,依靠这种机制,你还可以下载别人创建的 Container,甚至像 git 那样进行合并;
  • Docker Container 是可重用的,依赖于版本化机制,你很容易重用别人的 Container(叫 Image),作为基础版本进行扩展;
  • Docker Container 是可共享的,有点类似 github 一样,Docker 有自己的 INDEX,你可以创建自己的 Docker 用户并上传和下载 Docker Image;
  • Docker 提供了很多的工具链,形成了一个生态系统;这些工具的目标是自动化、个性化和集成化,包括对 PAAS 平台的支持等;

那么 Docker 有什么用呢?对于运维来说,Docker 提供了一种可移植的标准化部署过程,使得规模化、自动化、异构化的部署成为可能甚至是轻松简单的事情;而对于开发者来说,Docker 提供了一种开发环境的管理方法,包括映像、构建、共享等功能,而后者是本文的主题。

Docker 的安装和构成

Docker 官方本身提供了非常具体的安装教程,这里不说具体的安装过程,请参考 Docker 安装(Mac 系统),重要的是描述下原理和安装完成后的结构,好对 Docker 更好的了解。由于 LXC 本身不支持 Mac 内核,因此需要跑一个 VirtualBox 虚拟机(TinyCoreLinux)来安装,幸好 Docker 社区提供了一个非常方便的工具 boot2docker(其实就是一个 VBoxManage 的包装 shell 脚本),用于安装 Mac 下的整个 Docker 环境。具体的结构如下:

利用 Docker 构建开发环境详解

如图所示,安装完成后,具体情况如下:

  • 在 Mac 的 home 目录~/.boot2docker 下创建了虚拟机所需要的文件,其中 boot2docker.iso 是虚拟机映像,这是一个由 CD-ROM 引导的 TinyCoreLinux 系统;而 boot2docker-vm.vmdk 文件则是你的虚拟机磁盘,你所有的持久化数据都存放在这里,包括 docker 创建的 lxc 容器等文件。
  • 在 Mac 下,docker 被分为客户端 docker-client 和服务端 docker-daemon 两部分,如果是在 linux(比如 Ubuntu),实际上则是同一个可执行文件同时充当客户端和服务端。docker-daemon 可以监听 unix scoket,也可以在 tcp socket(默认端口为 4234),docker-client 会通过一个叫 DOCKER_HOST 的环境变量读取服务地址和端口,因此你应该在你的 bash_profile 文件里面添加这么一行:

export DOCKER_HOST=tcp://127.0.0.1:4243

docker-daemon 跑在虚拟机上,这个程序实际上就是接收 docker-client 发送过来的消息命令,创建、启动和销毁 lxc 容器,以及 docker 本身的版本管理、映像存储等等 运行你的第一个 docker 容器 安装完成后,就差不多可以开始创建和运行 docker 容器了,在这之前,你首先得下载一个 Image,什么是 Image?我们先来了解 docker 的 2 个基础概念:ImageContainer

Container 和 Image 在 Docker 的世界里,Image 是指一个只读的层(Layer),这里的层是 AUFS 里的概念,最直观的方式就是看一下 docker 官方给出的图:

利用 Docker 构建开发环境详解

Docker 使用了一种叫 AUFS 的文件系统,这种文件系统可以让你一层一层地叠加修改你的文件,最底下的文件系统是只读的,如果需要修改文件,AUFS 会增加一个可写的层(Layer),这样有很多好处,例如不同的 Container 可以共享底层的只读文件系统(同一个 Kernel),使得你可以跑 N 多个 Container 而不至于你的硬盘被挤爆了!这个只读的层就是 Image!而如你所看到的,一个可写的层就是 Container。

那 Image 和 Container 的区别是什么?很简单,他们的区别仅仅是一个是只读的层,一个是可写的层,你可以使用 docker commit 命令,将你的 Container 变成一个 Image,也就是提交你所运行的 Container 的修改内容,变成一个新的只读的 Image,这非常类似于 git commit 命令,感觉真棒!

实际上这就是 Docker 对 Container 映像的版本管理基石,AUFS 文件系统实在是太美妙了,更多细节可以参考 DotCloud 的这篇文章。

CentOS 6/ 7 系列安装 Docker http://www.linuxidc.com/Linux/2014-07/104768.htm

Docker 的搭建 Gitlab CI 全过程详解 http://www.linuxidc.com/Linux/2013-12/93537.htm

Docker 安装应用 (CentOS 6.5_x64) http://www.linuxidc.com/Linux/2014-07/104595.htm

Docker 和一个正常的虚拟机有何区别? http://www.linuxidc.com/Linux/2013-12/93740.htm

在 Docker 中使用 MySQL http://www.linuxidc.com/Linux/2014-01/95354.htm

Docker 将改变所有事情 http://www.linuxidc.com/Linux/2013-12/93998.htm

Docker 安装应用 (CentOS 6.5_x64) http://www.linuxidc.com/Linux/2014-07/104595.htm

Docker 是什么?让我来告诉你   http://www.linuxidc.com/Linux/2014-10/107967.htm

运行和退出

在了解了 Image 和 Container 的概念后,我们可以开始下载一个 Image,Docker 的好处就是提供了一个类似 github 的 Image 仓库管理,你可以非常方便 pull 别人的 Image 下来运行,例如,我们可以下载一个 ubuntu Image:

docker pull ubuntu:13.10

这里的 13.10 是一个 Tag,类似于 git 的 tag,这里的 tag 可以为你制定一个 ubuntu 的版本。下载完成后,执行 docker images 命令可以列出你已经下载或者自己构建的 image:(请允许我使用可爱的马赛克 :))

利用 Docker 构建开发环境详解

你可以看到 ubuntu:13.10 的大小为 178MB,以及它的 IMAGE ID。现在我们开始运行一个 Container,命令很简单,例如我们想运行一个执行 Shell 终端的 Container:

利用 Docker 构建开发环境详解

如你看到的,你已经进入到一个 Shell 里面,可以执行你想执行的任何命令,就和在 ubuntu 里面一样,进去后默认是在根目录 / 下,可以看到经典的 unix/linux 目录结构,以及你所运行的 bash 版本等信息。你可以给你的 Container 定一个名字,通过–name 选项,例如这里命名了 shell,日后你就可以直接用这个名字引用 Contanier。

退出一个 Container 也很简单,你直接 exit 就好了。其他更多的命令这里不做赘述,因为官方的文档已经非常全面,这里只是给一个直观的初步印象。下面进入主题。

更多详情见请继续阅读下一页的精彩内容 :http://www.linuxidc.com/Linux/2014-10/107969p2.htm

端口映射

和磁盘映射一样,你有时候会需要将 Container 的端口映射到 host 主机上,同样蛋疼的是,由于多了一层 VM,端口映射也显得比较麻烦。首先你需要设置 VirtualBox 的端口映射,然后再将 Container 的端口映射到你的 VM 里面:

利用 Docker 构建开发环境详解

具体是这么做的,通过 2 条命令:

boot2docker ssh -L 8000:localhost:8000
docker run -i -t -p 8000:8000

也就是说在 docker run 的时候通过 - p 选项指定要映射的端口到 VM,而 boot2docker ssh 命令则是将 VM 的 8000 端口映射到了 host(Mac) 的 8000 端口,这样你就可以通过 Mac 的 localhost:8000 访问 Container 的 8000 端口了。其实,有另一种解决方案就是你不用映射到 host(Mac),而是直接登录到 VM 里面进行访问就好了,boot2docker ssh 就可以登录到 VM,这样就类似于你的 host 是 Ubuntu,但这种解决方案的问题是这个 ubuntu 太弱了(TinyCoreLinux),如果你在这个 ubuntu 里面开发代码,或者是运行浏览器,是非常蛋疼的事情,关键还是这个 ubuntu 是每次重启都会复原的!所以我建议还是做多一层映射好了。最后,实际上在 VM 里面,你是可以直接访问所有的 Container 的端口的,因为 VM 到 Container 的网络都是桥接的。

其他的一些坑

在使用的过程中,还遇到一些不少的坑:

  1. /etc/hosts 文件无法修改,这样你就不能自己做域名解析
  2. VM 的系统时间是 UTC +0000 的,而且貌似无法修改
  3. Container 的 IP 无法指定为静态 IP,因此每次重启 Container 时,IP 可能会变化

第 1 个问题的解决方案是通过安装 dnsmasq 软件来做域名解析:

# 首先,在你的 Container 里面安装 dnsmasq 软件:

apt-get install dnsmasq

# 将以下文本添加到 /etc/dnsmasq.conf 文件的最后:

listen-address=127.0.0.1 resolv-file=/etc/resolv.dnsmasq.conf conf-dir=/etc/dnsmasq.d user=root

# 接着在 /etc/dnsmasq.d/ 目录下新建一个文件,随意起个名字

vi /etc/dnsmqsq.d/dns.conf

# 指定你要映射的域名,例如 google.com,则将下面贴进 dns.conf 文件

address=”/google.com/172.17.0.4″

# 最后退出容器,重启启动容器时,通过 -dns 选项指定域名服务器

docker run -i -t -dns 127.0.0.1 -dns 8.8.8.8 dev:base /bin/bash

# 一定要注意上面添加 google 的域名服务器 8.8.8.8,否则你访问不了外网

# 进去 Container 后,启动 dnsmasq,这样你就能够 ping google.com 了

/etc/init.d/dnsmasq start

第 2 个问题的解决方案就稍微麻烦些,起码我没有找到更好的解决方案,我是将 boot2docker.iso 文件重新制作一次来解决这个问题的:

# 首先你需要将 boot2docker.iso 文件 mount 到一个目录下

hdiutil mount ~/.boot2docker/boot2docker.iso

# 系统会 mount 到 /Volumes/boot2docker 目录下,然后你最好将这下面的东西 copy 出来到一个另外的目录,这样我们好制作一张新的 ISO

cp -r /Volumes/boot2docker/* ~/tmp/

# 接着我们修改以下文件

vi ~/tmp/boot/isolinux/isolinux.cfg

# 将其中的以下这行修改:

append loglevel=3 user=docker console=ttyS0 console=tty0 nomodeset norestore base

# 修改为:(其实就是加了 tz 的启动参数),然后保存

append tz=CST-8 loglevel=3 user=docker console=ttyS0 console=tty0 nomodeset norestore base

# 接着你必须在 ubuntu 环境下重新制作 ISO 文件,你可以利用 docker 跑一个 ubuntu,哈哈,假设你将 boot2docker 目录 copy 到了 ubuntu 的 /src/ 目录下,那么接着这么做

# 安装 xorriso 命令

apt-get install xorriso

# 构建 ISO 映射

xorriso -as mkisofs -J -R -V boot2docker -no-emul-boot -boot-load-size 4 -boot-info-table -b boot/isolinux/isolinux.bin -c boot/isolinux/boot.cat -o /boot2docker.iso /src/

# 这样就生成了 /boot2docker.iso 文件,最后你就可以替换到 VM 的启动 ISO 文件了,然后重启 VM 了

boot2docker restart

# 最后你必须设置你的 VM 为正确的时间,使用 date -s 命令,最后用 date 命令查看,你就能看到 CST 时区的正确时间了

Sun Mar 30 00:27:13 CST 2014

# 对于你启动的 container,你都必须重新设置 TZ 环境变量,否则即使 VM 是 CST-8,你的 container 还是 UCT +00:00 的时间

export TZ=’CST-8′

第三个问题暂时无法解决(可能需要编辑底层的 LXC 配置文件)。

docker 的限制以及后续的一些想法

docker 其实还是有一些限制的:

  • 要求你的环境是 Linux 的,而且内核必须很新(>= 2.6.27 (29)),这其实是 LXC 本身的限制,和 docker 无关
  • docker 的 Container 目前 host 是不能修改的,当然有解决方案(dnsmasq)
  • docker 的 Container 也暂时无法指定静态 IP

用 docker 作为开发环境甚至是生产环境其实还有很多地方值得尝试:

  • 在团队内部构建本地的仓库,标准化所有的开发环境,使得团队的新人可以快速上手
  • 在生产环境部署 docker,这其实是 PAAS 的虚拟化和自动化的一种方式,利用 LXC 和 Docker 能够更便捷地实施 PAAS
  • 尝试用 docker 做分布式集群模拟和测试,成本会更加低廉,更加容器维护

Docker 的详细介绍 :请点这里
Docker 的下载地址 :请点这里 

  本文永久更新链接地址 :http://www.linuxidc.com/Linux/2014-10/107969.htm

正文完
星哥说事-微信公众号
post-qrcode
 
星锅
版权声明:本站原创文章,由 星锅 2022-01-20发表,共计14801字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中