docker使用小结

最近试用了下docker,放在这里做个总结

docker是PAAS层面的虚拟化技术,它基于LXC(Linux Container)技术实现了container之间的隔离,相比于vm更为轻量级。这种轻量级可隔离的特点使得docker可以解决程序员大家开发环境时遇到的以下几个问题:

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

因为docker依赖linux的特性,在mac上需要使用虚拟机。我主要是在mac上利用virtualbox+boot2docker+docker-compose来实现的。

docker的安装与配置

  1. 安装virtualbox
  2. 安装docker:brew install boot2docker&& brew install docker
  3. boot2docker init
  4. 设置环境变量
    • export DOCKER_HOST=tcp://192.168.59.103:2376 (这个ip要通过boot2docker ip看一下,init时也会给出提示)
    • export DOCKER_CERT_PATH=/Users/ziqian/.boot2docker/certs/boot2docker-vm
    • export DOCKER_TLS_VERIFY=1
  5. boot2docker up

  6. (optional) 由于官方网站需要翻墙,所以可能需要设置docker hub代理:http://stackoverflow.com/questions/24489265/docker-boot2docker-set-http-https-proxies-for-docker-on-osx

  1. boot2docker restart
  2. 验证是否配置成功:
    • docker pull hello-world
    • docker run hello-world

Dockerfile简介

Dockerfile是用来描述一个docker image的生成过程的文件。在一个含有Dockerfile的文件夹中,通过 docker build imagename . 命令即可自动build docker image(注意命令中的“.”不能丢)。下面以redis官方提供的docker file为例讲讲dockerfile。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
FROM debian:wheezy
# add our user and group first to make sure their IDs get assigned consistently, regardless of whatever dependencies get added
RUN groupadd -r redis && useradd -r -g redis redis
RUN apt-get update && apt-get install -y --no-install-recommends \
ca-certificates \
curl \
libc6-i386 \
&& rm -rf /var/lib/apt/lists/*
# grab gosu for easy step-down from root
RUN gpg --keyserver pool.sks-keyservers.net --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4
RUN curl -o /usr/local/bin/gosu -SL "https://github.com/tianon/gosu/releases/download/1.2/gosu-$(dpkg --print-architecture)" \
&& curl -o /usr/local/bin/gosu.asc -SL "https://github.com/tianon/gosu/releases/download/1.2/gosu-$(dpkg --print-architecture).asc" \
&& gpg --verify /usr/local/bin/gosu.asc \
&& rm /usr/local/bin/gosu.asc \
&& chmod +x /usr/local/bin/gosu
ENV REDIS_VERSION 3.0.4
ENV REDIS_DOWNLOAD_URL http://download.redis.io/releases/redis-3.0.4.tar.gz
ENV REDIS_DOWNLOAD_SHA1 cccc58b2b8643930840870f17280fcae57ed7675
# for redis-sentinel see: http://redis.io/topics/sentinel
RUN buildDeps='gcc gcc-multilib libc6-dev-i386 make' \
&& set -x \
&& apt-get update && apt-get install -y $buildDeps --no-install-recommends \
&& rm -rf /var/lib/apt/lists/* \
&& mkdir -p /usr/src/redis \
&& curl -sSL "$REDIS_DOWNLOAD_URL" -o redis.tar.gz \
&& echo "$REDIS_DOWNLOAD_SHA1 *redis.tar.gz" | sha1sum -c - \
&& tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=1 \
&& rm redis.tar.gz \
&& make -C /usr/src/redis 32bit \
&& make -C /usr/src/redis install \
&& rm -r /usr/src/redis \
&& apt-get purge -y --auto-remove $buildDeps
RUN mkdir /data && chown redis:redis /data
VOLUME /data
WORKDIR /data
COPY docker-entrypoint.sh /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
EXPOSE 6379
CMD [ "redis-server" ]

Dockerfile主要格式如下:

1
2
# Comment
INSTRUCTION arguments

主要的INSTRUCTION有这样几个

  • 第一行的FROM指的是从哪个镜像开始创建,一般来讲docker image都是在一个image的基础上创建
  • RUN build时在linux中运行的具体命令。这里注意如果你的几个命令有上下文依赖,貌似需要写到一个RUN内而不是分成多个RUN写
  • MAINTAINER 镜像创建者
  • CMD 默认的container启动时的指定服务,镜像启动时可以通过输入参数更改。一个image只能有一个CMD,多条CMD执行最后一个
  • EXPOSE container内部服务开启的端口。在mac上他其实只是对虚拟机打开了端口,主机上要用还得在启动container时,做host-container的端口映射.
    • vbox映射端口的命令$ VBoxManage modifyvm “boot2docker-vm” –natpf1 “redis,tcp,,6379,,6379”
    • 这样就把虚拟机的6379映射到mac上
  • ENV 设置环境变量
  • VOLUME 将本地文件夹挂在到container中
  • WORKDIR 切换目录使用

其余Dockerfile相关命令请见官方文档

启动docker

  • 注,如果希望通过docker-compose管理container,可以查看下文的docker-compose来解决

docker run是启动一个container的命令,格式为docker run [OPTIONS] IMAGE [COMMAND] [ARG...],这里以启动redis为例

1
docker run -v /myredis/conf/redis.conf:/usr/local/etc/redis/redis.conf --name myredis redis redis-server /usr/local/etc/redis/redis.conf

这里的COMMAND是OPTIONS是/myredis/conf/redis.conf:/usr/local/etc/redis/redis.conf –name myredis,COMMAND是redis-server,ARG是redis-server的这条命令的参数,和docker本身就没关系了。

这个docker是用自己本地的redis.conf启动的。这里重要的参数是:

  • -v 将本机路径映射到docker内部
  • –name 给container起名

还有两个重要的参数

  • –link 链接其他容器,比如你再启动一个redis-sentinel时就可以将myredis link给他
  • -w 指定workdir

其他参数可以看手册docker run help

启动好之后,如果之前的端口映射正确,你就可以通过redis-client直接通过本地的6379链接container里的redis服务了

注意事项

  • 输入docker命令后无反应时,可能是无法连接到boot2docker。解决方案
    • 查看boot2docker ip:boot2docker ip
    • 修改环境变量: export DOCKER_HOST=tcp://${ip}:2376
  • 第一次使用docker run创建container之后,container不需要重复创建,只需要通过docker ps -a查看container的状态,并使用docker start ${container_name}启动挂起的container即可。

docker-compose

docker-compose是用来在docker中定义和运行复杂应用的小工具,比如在一个文件中定义多个容器,只用一行命令就可以让一切就绪并运行。并且它支持集群中分布式部署,在部署大型应用时更有优势。

安装docker-compose

  1. pip install -U docker-compose
  2. chmod +x /usr/local/bin/docker-compose

编写docker-compose.ylm

为了体现其部署的优势,我给出一个同时启动redis和redis-sentinel的ylm。相关的配置信息标在了注释里

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#container名称
redis-sentinel:
#image表示该container使用的image。docker-compose同样支持使用dockerfile直接build image。这时需要使用build和dockerfile两个标签
image: redis
#container默认的命令
command: redis-sentinel /conf/sentinel.conf
#该container与宿主机的文件映射,宿主机路径在前。在mac中宿主机是virtualbox中的虚拟机boot2docker-vm。所以还需要做mac到vm的映射,port同理。
volumes:
- ./conf:/conf
#该container和其他container的映射关系,这里sentinel就是连接了redis
links:
- redis
#container与宿主机的端口映射,宿主机端口在前
ports:
- "26379:26379"
redis:
image: redis
command: redis-server
ports:
- "6379:6379"

关于yml更详细的说明请见 官方文档

运行compose

在有docker-compose.yml的文件夹内执行docker-compose run –service-ports redis-sentinel
这里就成功启动了一个redis-sentinel,并且docker-compose会把它依赖的(也就是link的)container(这里是redis)都启动起来。

  • 注意,docker-compose在设计上对于docker-compose run命令默认不开放端口给宿主机。所以使用–service-ports选项。具体讨论请见github相关页面

本文采用创作共用保留署名-非商业-禁止演绎4.0国际许可证,欢迎转载,但转载请注明来自http://thousandhu.github.io,并保持转载后文章内容的完整。本人保留所有版权相关权利。

本文链接:http://thousandhu.github.io/2015/10/12/docker使用小结/