Contents
  1. 1. 一、docker不是虚拟机
  2. 2. 二、开始使用docker
    1. 2.1. 在ubuntu下安装docker
    2. 2.2. docker的镜像
  3. 3. 三、使用dockerfile构建镜像
    1. 3.1. FROM
    2. 3.2. USER
    3. 3.3. RUN
    4. 3.4. ENV
    5. 3.5. WORKDIR
    6. 3.6. COPY
    7. 3.7. CMD
    8. 3.8. ENTRYPOINT
    9. 3.9. 完整的dockerfile
    10. 3.10. build镜像
  4. 4. 四、网络
  5. 5. 五、启动
  6. 6. 六、后记

一、docker不是虚拟机

docker有别于传统虚拟化,他不是一个虚拟机,而是容器,本质就是在主机上运行的一个特殊的进程。所以docker比虚拟机更轻、启动更快、调用底层更直接。
关于docker容器和虚拟机的更多对比,可以参考以下一些文章:
虚拟机与Docker有何不同?
反思|容器与虚拟机的真正区别在哪里?

二、开始使用docker

在ubuntu下安装docker

添加使用HTTPS传输的安全依赖和CA证书软件

1
sudo apt-get install     apt-transport-https     ca-certificates     curl     software-properties-common

使用阿里的源安装

1
2
3
4
5
curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo apt-key add -
sudo add-apt-repository \
"deb [arch=amd64] https://mirrors.aliyun.com/docker-ce/linux/ubuntu \
$(lsb_release -cs) \
stable"

腾讯云的源

1
2
3
4
5
curl -fsSL https://mirrors.cloud.tencent.com/docker-ce/linux/ubuntu/gpg | sudo apt-key add -
sudo add-apt-repository \
"deb [arch=amd64] https://mirrors.cloud.tencent.com/docker-ce/linux/ubuntu \
$(lsb_release -cs) \
stable"

以上命令会添加稳定版本的 Docker CE APT 镜像源,如果需要最新版本的 Docker CE 请将 stable 改为 edge 或者 test。从 Docker 17.06 开始,edge test 版本的 APT 镜像源也会包含稳定版本的 Docker。

安装docker-ce

1
2
sudo apt update
sudo apt-get install docker-ce

经过以上步骤,docker最新版就安装好了。
也可以安装指定版本,使用命令查看可用版本:

1
2
3
4
5
6
7
8
ubuntu@wx:/etc/kubernetes$ apt-cache madison docker-ce
docker-ce | 17.09.0~ce-0~ubuntu | https://mirrors.aliyun.com/docker-ce/linux/ubuntu xenial/stable amd64 Packages
docker-ce | 17.06.2~ce-0~ubuntu | https://mirrors.aliyun.com/docker-ce/linux/ubuntu xenial/stable amd64 Packages
docker-ce | 17.06.1~ce-0~ubuntu | https://mirrors.aliyun.com/docker-ce/linux/ubuntu xenial/stable amd64 Packages
docker-ce | 17.06.0~ce-0~ubuntu | https://mirrors.aliyun.com/docker-ce/linux/ubuntu xenial/stable amd64 Packages
docker-ce | 17.03.2~ce-0~ubuntu-xenial | https://mirrors.aliyun.com/docker-ce/linux/ubuntu xenial/stable amd64 Packages
docker-ce | 17.03.1~ce-0~ubuntu-xenial | https://mirrors.aliyun.com/docker-ce/linux/ubuntu xenial/stable amd64 Packages
docker-ce | 17.03.0~ce-0~ubuntu-xenial | https://mirrors.aliyun.com/docker-ce/linux/ubuntu xenial/stable amd64 Packages

使用命令安装指定版本:

1
sudo apt-get install docker-ce=<VERSION>

使用systemctl命令查看docker进程是active状态

1
2
3
4
5
6
7
8
9
ubuntu@ubuntu1:~$ systemctl status docker
● docker.service - Docker Application Container Engine
Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled)
Active: active (running) since 五 2017-10-20 17:01:59 CST; 28min ago
Docs: https://docs.docker.com
Main PID: 8530 (dockerd)
CGroup: /system.slice/docker.service
├─8530 /usr/bin/dockerd -H fd://
└─8538 docker-containerd -l unix:///var/run/docker/libcontainerd/docker-containerd.sock --metrics-interval=0 --start-timeout

docker的镜像

docker官方仓库也有很多镜像可以选择,使用docker search命令可以搜索到.
例如我搜索ubuntu镜像,结果显示有很多,其中有官方的也有第三方build的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
ubuntu@wx:~/compose-hadoop-spark/hadoop$ docker search ubuntu
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
ubuntu Ubuntu is a Debian-based Linux operating s... 6677 [OK]
dorowu/ubuntu-desktop-lxde-vnc Ubuntu with openssh-server and NoVNC 136 [OK]
rastasheep/ubuntu-sshd Dockerized SSH service, built on top of of... 108 [OK]
ansible/ubuntu14.04-ansible Ubuntu 14.04 LTS with ansible 87 [OK]
ubuntu-upstart Upstart is an event-based replacement for ... 80 [OK]
neurodebian NeuroDebian provides neuroscience research... 40 [OK]
ubuntu-debootstrap debootstrap --variant=minbase --components... 31 [OK]
nuagebec/ubuntu Simple always updated Ubuntu docker images... 22 [OK]
tutum/ubuntu Simple Ubuntu docker images with SSH access 18
1and1internet/ubuntu-16-nginx-php-phpmyadmin-mysql-5 ubuntu-16-nginx-php-phpmyadmin-mysql-5 16 [OK]
ppc64le/ubuntu Ubuntu is a Debian-based Linux operating s... 11
aarch64/ubuntu Ubuntu is a Debian-based Linux operating s... 9
i386/ubuntu Ubuntu is a Debian-based Linux operating s... 8
codenvy/ubuntu_jdk8 Ubuntu, JDK8, Maven 3, git, curl, nmap, mc... 3 [OK]
darksheer/ubuntu Base Ubuntu Image -- Updated hourly 3 [OK]
1and1internet/ubuntu-16-apache-php-7.0 ubuntu-16-apache-php-7.0

使用docker pull ubuntu:version命令,可以把镜像下载下来使用。
第一步我们需要下载一个ubuntu 16的镜像:

1
sudo docker pull ubuntu:16.04

三、使用dockerfile构建镜像

我们的目标是吧hadoop+spark集成环境构建成自己的镜像,使用镜像搭建3节点的spark集群。
在这个过程中学习使用dockerfile,dockerfile定义了很多命令,我们下面会介绍我们使用到的命令,更多命令用法可以参考官方文档。

FROM

FROM意思是使用一个镜像做基础,我们使用刚刚下载的ubuntu镜像

1
FROM ubuntu:16.04

USER

USER意思是切换用户,必须要用户存在才可以,后续操作就使用这个用户执行

RUN

RUN是运行命令的意思,构建镜像就是在原有镜像基础进行定制化,必须会运行一些命令,例如新建帐户、改权限、下载安装包等
示例:新建hadoop用户并赋予sudo免密权限

1
2
3
4
5
RUN groupadd hadoop \
&& useradd -g hadoop -G sudo -m hadoop \
&& chmod u+w /etc/sudoers \
&& echo 'hadoop ALL=(ALL) NOPASSWD: ALL' >> /etc/sudoers \
&& chmod u-w /etc/sudoers

ENV

ENV是添加环境变量,对后续操作生效,例如JAVA_HOME

1
ENV JAVA_HOME /usr/lib/jvm/java-8-openjdk-amd64

后续的RUN命令可以使用$JAVA_HOME

WORKDIR

指定容器启动后的工作目录,可以把程序或脚本放在这个目录

COPY

COPY是复制文件,可以把文件复制进镜像,这里我们把hadoop的配置文件预先写好一并复制进镜像

1
COPY ./*-site.xml $HADOOP_PREFIX/etc/hadoop/

CMD

CMD是启动镜像默认运行的命令,如果docker run指定了其他命令则CMD会忽略。
需要注意进程不要后台运行,后台运行的命令在容器看来驻留后台的时候就已经结束了,记住docker是容器。所以要保持容器运行,命令需要前台运行。

1
CMD [ "sh", "-c", "sudo service ssh start; bash"]

ENTRYPOINT

ENTRYPOINT 指令可让容器以应用程序或者服务的形式运行,ENTRYPOINT 不会被忽略,一定会被执行,即使运行 docker run 时指定了其他命令。

1
ENTRYPOINT ["/bin/echo", "Hello"]  

如果同时存在ENTRYPOINT和CMD,CMD会被当作参数传入ENTRYPOINT,docker run运行时指定的命令会作为参数覆盖CMD,传入ENTRYPOINT成为新参数。

k8s中,在pod定义command和args会覆盖镜像的ENTRYPOINT和CMD参数

Image Entrypoint Image Cmd Container command Container args Command run
[/ep-1] [foo bar] [ep-1 foo bar]
[/ep-1] [foo bar] [/ep-2] [ep-2]
[/ep-1] [foo bar] [zoo boo] [ep-1 zoo boo]
[/ep-1] [foo bar] [/ep-2] [zoo boo] [ep-2 zoo boo]

更完整的定义参考Dockerfile介绍

完整的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
FROM ubuntu:16.04
USER root
# install base tools
RUN apt update \
&& apt install -y curl tar sudo openssh-server openssh-client rsync openjdk-8-jdk
ENV JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64 PATH=$PATH:$JAVA_HOME/bin
# add hadoop user and passwordless ssh
RUN groupadd hadoop \
&& useradd -g hadoop -G sudo -m hadoop \
&& chmod u+w /etc/sudoers \
&& echo 'hadoop ALL=(ALL) NOPASSWD: ALL' >> /etc/sudoers \
&& chmod u-w /etc/sudoers
USER hadoop
RUN ssh-keygen -q -N "" -t rsa -f ~/.ssh/id_rsa \
&& cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys \
&& echo "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCfyJOeBBSHCQVu6/ ubuntu@wx" >> ~/.ssh/authorized_keys \
&& chmod 600 ~/.ssh/authorized_keys \
&& echo 'StrictHostKeyChecking no' > ~/.ssh/config
# download and config hadoop
RUN curl -s http://mirror.bit.edu.cn/apache/hadoop/common/hadoop-2.8.1/hadoop-2.8.1.tar.gz |sudo tar -xz -C /usr/local/ \
&& sudo chown -R hadoop:hadoop /usr/local/hadoop-2.8.1 \
&& sudo ln -s /usr/local/hadoop-2.8.1 /usr/local/hadoop \
&& mkdir /usr/local/hadoop/tmp
ENV HADOOP_PREFIX /usr/local/hadoop
RUN sudo sed -i '/^export JAVA_HOME/ s:.*:export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64\nexport HADOOP_PREFIX=/usr/local/hadoop\nexport HADOOP_HOME=/usr/local/hadoop\n:' $HADOOP_PREFIX/etc/hadoop/hadoop-env.sh \
&& sudo sed -i '/^export HADOOP_CONF_DIR/ s:.*:export HADOOP_CONF_DIR=/usr/local/hadoop/etc/hadoop/:' $HADOOP_PREFIX/etc/hadoop/hadoop-env.sh
COPY ./*-site.xml $HADOOP_PREFIX/etc/hadoop/
COPY ./slaves $HADOOP_PREFIX/etc/hadoop/slaves
# download and config spark
RUN curl -s https://d3kbcqa49mib13.cloudfront.net/spark-2.2.0-bin-hadoop2.7.tgz |sudo tar -xz -C /usr/local/ \
&& sudo chown -R hadoop:hadoop /usr/local/spark-2.2.0-bin-hadoop2.7 \
&& sudo ln -s /usr/local/spark-2.2.0-bin-hadoop2.7 /usr/local/spark
ENV SPARK_HOME /usr/local/spark
COPY ./slaves $SPARK_HOME/conf/slaves
RUN echo 'export HADOOP_CONF_DIR=/usr/local/hadoop/etc/hadoop' >> $SPARK_HOME/conf/spark-env.sh
COPY ./start-service.sh /home/hadoop/start-service.sh
RUN sudo chmod +x /home/hadoop/start-service.sh
CMD [ "sh", "-c", "sudo service ssh start; bash"]

build镜像

使用命令docker build构建镜像,进入Dockerfile所在目录,运行如下命令

1
sudo docker build -t spark:0.1 .

需要注意命令中’.’代表当前目录,这影响到Dockerfile中的参数环境。
-t 镜像名称:版本

四、网络

搭建3节点集群需要把节点放在同一个虚拟网络环境下,节点间通过hostname可以互联。docker在这方面提供了方便的实现,我们通过简单的命令创建一个叫net1的网络环境。

1
sudo docker network create --driver=bridge net1

使用docker network查看当前存在的网络

1
2
3
4
5
6
ubuntu@wx:~/dockerimg/hadoop$ sudo docker network ls
NETWORK ID NAME DRIVER SCOPE
bbc1b008d971 bridge bridge local
6c90e7d1cdd9 host host local
2d74b1e3b79d net1 bridge local
e4753da64f2b none null local

五、启动

我们先启动2个slave节点,使用如下命令

1
sudo docker run -itd --rm --net=net1 -v /data/hadoop/slave1/tmp:/usr/local/hadoop/tmp  -h hadoop-slave1 --name hadoop-slave1 spark:0.1

-v 把本地目录/data/hadoop/slave1/tmp 挂在到容器目录/usr/local/hadoop/tmp
–rm 当容器进程退出就删除容器
–it 交互模式 -d 后台运行
-h hostname
slave1改成slave2启动节点2

启动master节点

1
sudo docker run -it --rm --net=net1 -p 8080:8080 -p 8020:8020 -p 50070:50070  -v /data/hadoop/master/tmp:/usr/local/hadoop/tmp  -h hadoop-master --name hadoop-master spark:v0.3

-p 端口映射 本地端口:容器端口

master容器启动后直接就进入了bash交换操作,然后像一般集群那样运行start-all.sh启动hadoop和spark

六、后记

docker学习下来比传统虚拟机有很多不一样,像kvm这种虚拟机需要底层硬件支持才能发挥更好性能,可以说全面虚拟了一个服务器,包括硬件。容器就完全在软件方面做功夫,把利用LXC把资源给隔离出来,使进程跑在独立的环境上。
你要虚拟出一个Windows?docker帮不了你。
接下来会继续玩docker-compose。

Contents
  1. 1. 一、docker不是虚拟机
  2. 2. 二、开始使用docker
    1. 2.1. 在ubuntu下安装docker
    2. 2.2. docker的镜像
  3. 3. 三、使用dockerfile构建镜像
    1. 3.1. FROM
    2. 3.2. USER
    3. 3.3. RUN
    4. 3.4. ENV
    5. 3.5. WORKDIR
    6. 3.6. COPY
    7. 3.7. CMD
    8. 3.8. ENTRYPOINT
    9. 3.9. 完整的dockerfile
    10. 3.10. build镜像
  4. 4. 四、网络
  5. 5. 五、启动
  6. 6. 六、后记