Docker 简介

包括:
一. Docker 介绍
二. Docker 网络配置(容器互联*) 和 Dockerfile 
三. Docker 的一些常用命令
四. Docker 的实际部署
五. 一些坑 总结


一. Docker 介绍
1.1 基本概念
          Docker 是由 Go 语言编写,一个快速部署的 轻量级虚拟技术项目, 它允许开发人员把自己的程序 和 开发环境一起打包,制作成一个 Docker 的image(镜像),这样部署到服务器上,也只需要下载这个 image 镜像将程序跑起来, 免去了每次安装依赖和环境的麻烦,还能做到应用间的隔离。
          Docker 系统有两个程序,服务器端 和 客户端。服务器端 是一个服务进程,管理所有容器。客户端 相当于服务器端的远程控制器。

为什么要用Docker:
  • 对系统资源利用率高:一个主机可以运行上千个 Docker。基本不消耗资源,传统的虚拟机的方式,10个 不同的应用就要起10个虚拟机,而Docker 只需要启动 10 个 隔离的应用即可。
  • Docker 容器几乎可以在任何平台上跑,比较容易迁移。
  • 启动快。
  •  …...

1.2 镜像,容器,仓库
Docker 有三大概念: 镜像(image),容器(container),仓库。
  • 镜像:可以用来创建 Docker 容器(container)。
  • 容器:是镜像 创建的运行实例。可以被启动,开始,停止,删除。每个容器相互隔离,保证安全。容器可以看成是简易版的 Linux 环境,并且镜像 是 只读的,容器可以创建一层可写层作为最上层。
  • 仓库:是存放镜像文件的场所。仓库注册服务器包括多个仓库,每个仓库又包括了 多个镜像。仓库又分为公开仓库 和 私有仓库,最大的公开仓库是 Docker Hub。(可以理解成 github 这样的)

          总的来说,我们可以把 运行的操作系统(比如 ubuntu,centos),环境(比如 java,mysql,tomcat),应用程序(自己的代码)等打包成一个 image,然后 就可以 执行 run,那么 就变成一个 container,此时我们设置一些命令,也可以说是脚本,那么应用就可以跑起来了。
          并且,这个 image 可以复用,比如说我有另外一个程序,也是用这套环境,那么我就不用再重新搭建环境了,直接用这个 image 即可。
          除此之外, 外部能不能访问我这个container,都可以通过网络设置来控制,比如说,我的 mysql 跑在一个 container 中,我不想让外部访问我的 mysql,只能让另外一个 container 访问(也就是我的应用程序), 那么也是可以做到。 这就是 docker 的一个 隔离机制。
          最后,container 之间是 也是相互不影响的。
          这也是 docker 的一些好处。

二. Docker 网络配置 和 Dockerfile 

2.1 Docker 网络配置 :

          如下图所示: 一个 Docker 中可以 开多个 container,每个 container 其实可以理解成独立的 一个服务器,即可以让别人访问,也可以不让别人访问。
          当需要给别人访问的时候,这个 别人分为两种,一种 是 其他的 container,一种是 public(即外部 + 其他container)。具体怎么设置,下文再说。从这个图可以看出,Docker 更适合于 分布式的应用,把不同的服务 放在 不同的 container 中,彼此可以相互的访问,并且可以设置外部访问不了。 同时,这些 服务相互不影响,可以各自用各自的环境,比如说一个 用 centos 系统,另外一个中 ubuntu系统,一个 用mysql 数据库,一个用 redis,等等。
          下图中,可以在docker run images 的时候(也就是 把container 启动的时候) 设置好 80:8080 ,表示 外部如果访问 本机的 80端口,那么 会转向开放了 8080 端口的 container1 中。如果container1 没有开放任何 端口,那么container1 谁也访问不了(包括其他container)。 


          上面说的80:8080 可以用下面这个图再解释一下: 

          也就是说,本来主机有操作系统 centos,外部可以访问这个主机的端口。此时,这个主机又开了多个 container,这些container 也是系统,同样,他们也有端口,所以就涉及到 主机的端口转到 内部 container 的系统的端口。可以联想下 虚拟机 和 nginx 的转发。

容器互联:
          容器互联是个 Docker 比较重要的知识。
          使用 - - link 是参数可以让容器之间 安全的进行交互。格式为 - - link name:alias   name表示要链接的容器的名称,alias 表示 这个链接的别名。 
          Docker 在两个互联的容器之间创建了一条安全隧道,而且不用映射他们的端口到宿主主机上。在启动 db 容器的时候并没有使用 -p 或者 -P 标记,从而避免暴露了数据库端口到外部网络上。 

具体如何进行容器间互联:
  1. 定义一个 A 容器 :比如说 docker run -it  - -name  “container1”       //注意,一定要定义这个名字,下面要用到
  2. 定义一个 B 容器 并且链接A 容器 :比如说 docker run -it - -name “container2” - -link container1:xxx  images
完成链接。
QA:
  1. 第二句怎么理解:docker run -it 就不说了,正常的docker启动。  - -name 就是指定 这个container 叫什么名字。 - -link  表示我要进行container 互联,固定的。 container1:xx  表示 我要连哪个 container, xx 表示 别名,你可以理解为这个链接的名字是什么。
  2.  怎么知道连OK了? 用第二个container 链接第一个 container ,那么去到第二个container 中,vi /etc/hosts 你就会发现连OK了。如下图是我连好了的:

          这个hosts 文件 看最后一行,就是表示 我连上了 名字为 kong_test1 的container,这个kong_test1 的container 的IP 是 172.17.0.3(自己的看第一行是 172.17.0.6),这个kong_test1 的 container id 是 56efdfefe3bb。这个链接的名称为 KConnection。
          最后你可以ping 一下 173.17.0.3 ,你会发现是通的。 


2.2 dockerfile :
          创建 images 有两种方式。
  1. 下载好别人的 image(也就是别人做好的环境),跑起来,此时变成了一个 container,然后在它的环境的基础上安装自己的一些东西。最后在 docker commit ,就会把这个 环境打包成一个 image。这个image 实际上就是别人的image+自己定制的部分。
  2. 使用docker file,这是一个文件,里面会有一行一行的命令, 直接用docker build,然后docker 就会执行这些命令,生成一个 image。那么 这些命令是什么,下面介绍。

例如如下是一个 我在阿里云上 测试的 dockerfile: 
FROM 9114c29f37a8

MAINTAINER wuhuachuan wuhuachuan712@163.com

COPY ./tomcat8/ /home/whc/tomcat/

CMD bash /home/whc/tomcat/apache-tomcat-8.0.27/bin/startup.sh && tail -f /home/whc/tomcat/apache-tomcat-8.0.27/logs/catalina.out

这4行的意思是:
  1. FROM:这个指令一开始必须要有,表示你的image 是基于什么image的。一般来说,我们最最开始的可以基于一个 centos系统的 image。
  2. MAINTAINER :告诉别人你的大名。
  3. 表示我要把 当前目录的 tomcat 的文件 复制到 container 中的 /home/whc/tomcat 目录中。当前 这个意思就是你现在在的这个系统,等你运行的时候,container 也会是一个在你系统内部的系统,这行的意思就是 复制到你 这个 container 系统中去。
  4. CMD :表示 当我的container 启动的时候,会帮我 自动运行bash …./startip.sh 和 tail … /catalina.out 这两个命令。其实这两个命令就是 启动tomcat 的意思。
所以说,这四行就可以创建一个 简单的 image,并且在启动的时候 会自动运行 tomcat,如果我们在web 程序放入到 tomcat 的 webapps 目录下,那么实际上就是 跑了我们的程序的意思。

          以上告诉一些大体的概念,细节暂时不用纠结。


三. Docker 的一些常用命令

3.1 运行 image
  1. 先用 docker ps -a 看看有没有容器,如果已经存在容器,那么使用 docker start  容器ID,即可。
  2. docker run -it a38c26f8f4b8 :docker run 是固定的,-it 表示 你运行后,会进入到 该 container 的终端,(Ps,你现在是在本机的终端中),这个数字就是表示 image 的 id。
  3. docker run -d  a38c26f8f4b8 :-d 表示运行了 这个 image,但是是后台运行,不会进入到该container 的终端,还是在现在这个系统的终端。
  4. docker run - -rm a38c26f8f4b8 :- - rm 表示 当里面的container 退出之后,该容器会自动删除。
  5. docker run -d -p 80:8080 a38c26f8f4b8 :其中 -p 80:8080 表示,当这个容器启动的时候,会开放8080 端口给外部docker。那么当有人请求 80 端口的时候,docker 就会把 80 转到 8080 端口,也就是我们的这个 容器中。如果里面有 tomcat 监听了8080 端口,那么实际上就是访问了 这个容器的 tomcat。

3.2 查看
  1. 查看目前有什么镜像:docker images。
  2. 查看目前正在运行的容器:docker ps。查看有什么容器: docker ps -a。

3.3 删除
  1. 删除容器: 先用 docker ps -a 查看容器的 id。然后执行 docker rm 容器Id。(Ps:如果容器还在运行,需要先运用 docker stop 容器ID,把这个容器先停掉。)
  2. 删除镜像:docker rmi 镜像ID。

3.4 创建镜像
          按照上面提到的方式,有两种创建方法:
  1. docker commit -m “创建注释” -a “你的用户名字”  容器ID 镜像仓库:标签。具体示例如下:
    1. docker commit -m “centos 加入了 java8镜像” -a “wuhuachuan” 8fa5fa9ba7f0 wuhuachuang/whc:centos-java8  这个表示 我的名字是 wuhuachuan,我的仓库 wuhuachuan/whc,标签是 centos-java8.
  2. 第二种创建方式是 使用 docker build -t ”wuhuachuan/whc:centos-java8” .  其中 有一个 点 ,表示 dockerfile在当前的目录中 。

3.5 暴露端口

          主要有 EXPOSE 和 -p/-P 两种方式,EXPOSE 是写在dockerfile 中, -p/-P 的方式是 在 docker run  的时候指定的。具体关于 怎么暴露,stackoverflow 上有一个 很好的解释: 




简单翻译下:
  • 如果你 不指定 EXPOSE  和 -p 那么 container 里面的服务 container 外部是肯定访问不了。
  • 如果你 EXPOSE 一个端口,service 里面的服务外面肯定是访问不了,但是其他容器可以访问。所以说这是容器互联这是比较好的方式。
  • 如果 你 EXPOSE 和 -p 一个端口,那么哪里都可以访问。
  • 如果你使用了 -p 不使用 EXPOSE 。docker 会有一个默认的 EXPOSE。也是哪里都可以访问。


四. Docker 的实际部署

          说下我目前在 阿里云上 做了的事情:
  1. 安装docker。
  2. 写dockerfile,如上的 dockerfile 代码。
  3. 执行 docker build。(具体如上代码) 。生成一个镜像。
  4. 执行 docker run -d  -p 80:8080 imageID。运行镜像,生成container,启动tomcat。
  5. 完。

          当然,中间由于学习的时候不懂 ,使用了无数次docker ps -a, docker images,docker rm,docker rmi 等命令。还是自己敲记忆深。

如下赋上 我工作时 生产环境下的 Dockerfile:
FROM ubuntu
ADD jdk-8u51-linux-x64.tar.gz /opt/
ADD dsc-cassandra-2.1.11-bin.tar.gz /opt/
ADD kong-0.5.4.trusty_all.deb /opt/
ENV JAVA_HOME=/opt/jdk1.8.0_51
ENV PATH=$JAVA_HOME/bin:$PATH
RUN apt-get update && apt-get install -y \
    dnsmasq-base \
    dnsmasq \
    openssl \
    curl
RUN dpkg -i /opt/kong-0.5.4.trusty_all.deb
EXPOSE 8000

       总体的意思是,基于 ubuntu,首先把 jdk,cassandra 数据库,kong 文件复制进去,然后设置环境变量,安装一些软件,安装我的kong,开放 8000 端口给内部 container 使用。(Kong 是什么可以参考另外一篇博文 微服务那个)



五. 一些坑 总结
  1. Tomcat 的启动
          容器运行完之后,就会自动退出,tomcat 的启动那么 以deamon 线程跑,docker 就会认为已经运行完了,那么就会退出,所以说tomcat 启动一会就会挂掉。(其实是整个 容器退出了,因为docker 认为结束了)。此时的解决办法 就是让 docker 认为 容器的任务还没有结束,可以使用如下: 



    2. 如下错误:

Do you want to continue? [Y/n] Abort.

The command '/bin/sh -c apt-get install dnsmasq-base' returned a non-zero code: 1

    解决办法:在dockerfile 中的 install 的时候,加上 -y  参数,表示 选择yes。即 apt-get -y install xxx.deb 即可。


    3.  如何进入 已经启动的容器:docker exec -it 容器id  /bin/bash


参考(建议全部看完):
  1. http://dockerpool.com/static/books/docker_practice/introduction/README.html



一些疑问:
在实际的部署中,遇到了一些困难,一个是设计上的,一个是具体部署细节上的。
设计上的:一般什么东西会放在Docker 中,我理解是 微服务,就也就是具体的业务模块代码,这些其实都是无状态的。那么对于有状态的,比如数据库,我们是否需要还放在 Docker 中跑。这样对于以后做数据库的集群或者分布式是否方便。再比如说 nginx 是否 需要放在 Docker中,还是和Docker 平级?
具体部署上:写dockerfile 文件的时候,你怎么保证写的这些命令不出错,写一条命令就 docker build 一次,然后再 run 进去看看ok不ok??还是说先run 进去,再安装好东西,再 history 拿到执行过的所有命令,再写到 dockerfile 中??

望赐教,3Q




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值