docker学习笔记(一)

   docker是一种容器技术,如今火的一塌糊涂,最近公司打算用docker统一开发、测试、预上线、上线环境,因此花了时间研究一下。
    docker是一种容器技术,以前是基于LXC容器,如今已经改为基于libcontainer了。研究了几天,对docker有如下总结:
    1)docker是一种容器技术,容器中包含了一个微型操做系统,咱们在容器中封装咱们要运行的程序环境,这样就节省了环境配置和维护的时间和人力成本,容器有本身的网络环境,能够定制其使用的cpu、内存和磁盘等资源,对于运维来讲,尤为是对于频繁发布的运维人员来讲,是个福音。听说亚马逊天天要发布上万次、谷歌也有几千次,其发布间隔已经到分钟级。固然这种发布,不只仅是docker的做用,其余一系列的自动化配置、自动化测试、自动化发布、自动化回滚都要跟上才行。
    2)docker的性能要低于裸机,因此在小型系统的运行环境中没有必要使用docker
    3)docker的稳定性须要注意,在上线以前须要进行充分的压力测试
    4)docker是基于linux的,因此windows和Mac都使用virtualBox虚拟机来实现的。
    5)docker能够很快的搭建测试环境,可是对于开发环境来讲,由于是另一台机器,因此调试、自动完成、代码提示都会有必定的问题,须要特殊的配置。
    6)docker不是虚拟机,是一个容器,更准确的来讲,是一个程序,因此启动容器须要指定启动程序,不然容器会启动失败,另外虽然容器是个微型操做系统,可是没有服务自动运行的概念,这一点对于有必定运维经验的同窗来讲容易混淆。
    7)容器的构建通常基于ubuntu、debian、centos等linux发行版,因此若是想构建本身的docker镜像,最好同时安装对应的虚拟机,测试一些命令,运行成功了,再放到Dockerfile中,不然会比较麻烦。
    8)构建容器有两种办法,一种是在现有镜像的基础上,登陆容器,更新容器,让后将容器内容保存为镜像,这种方法通常是初学者用来学习测试用,另一种是经常使用的Dockerfile,这个文件规定了容器构建的步骤和命令,能够重复运行,并能够根据本身的要求本身修改,获得新的镜像。
    9)镜像的得到:最权威的是hub.docker.com,能够在上面搜索到相应的须要的镜像,根听说明文档拉取镜像到本地就能够了,不过速度要慢一些,国内一些公司作了hub.docker.com的备份,能够从国内拉取镜像,速度要快的多,这种公司也很多,daoclound和灵雀云能够尝试一下
   10)能够创建本身的私有镜像中心,docker公司提供了一个docker-registry的镜像,能够直接使用,启动以后,就有了一个本身的镜像中心,在上面能够进行发布和拉取镜像的操做,这也算一个快速部署的例子吧,固然也能够在其基础上作定制。
   11)docker容器是不会保存文件的,若是容器中止,容器里所做的修改就不存在了,因此容器中须要保存的部分须要放在容器外,能够将宿主机的目录和文件,映射到容器内部,映射以后,若是容器内存在该文件或目录,会覆盖容器内的文件;还能够不指定宿主的目录文件,宿主机会自动生成一个文件,目录文件名是随机的。
   12)docker容器自己有本身的ip地址,当docker启动时,默认会建立一个docker0网桥,本机的容器都会从这个网桥获得一个地址,并与之互通,这个地址能够经过docker inspect命令看到,在本机能够直接用ip地址访问。可是其余机器就访问不了了。这个问题的解决方法不少,有的复杂,有的简单,最简单的方法是将容器的对外访问的端口暴露出来,映射到宿主机的端口,这样其余机器就能够访问了。若是容器之间须要访问,由于其ip地址是不肯定的,因此须要用容器链接来解决,容器链接本质上是将容器名称和容器IP关联起来,修改父容器的/etc/hosts,因此忽略IP链接问题。固然还有更复杂的,就是不创建docker0网桥,直接分配docker容器地址,配置路由,这个比较麻烦,须要研究一下iptables命令,不过有一些工具能够用来解决这个问题,这也是docker集群大规模部署的基础。感兴趣能够研究一下weave,kubernetes
   为方便起见,在linux虚拟机中作docker的实验,环境以下
   操做系统:CentOS 7 
   内存: 3.2G
   CPU核数 : 2
   实验内容:搭建ngixn 1.9 + php-fpm 5.6 + mysql 5.6
   IP:172.16.10.138
   步骤以下:
   1)安装docker,根据官方网站的步骤
        a) 更新软件包
            $ yum upate
        b) 更新yum资源库
            $ tee /etc/yum.repos.d/docker.repo <<-'EOF'
            [dockerrepo]
            name=Docker Repository
            baseurl=https://yum.dockerproject.org/repo/main/centos/$releasever/
            enabled=1
            gpgcheck=1
            gpgkey=https://yum.dockerproject.org/gpg
            EOF
  c)安装docker
      $ yum install docker-engine
            $ systemctl start docker
            $ systemctl enable docker
            须要启动docker服务才能够,不然docker没法使用,上面将docker服务设置为自动启动
       d)docker命令简介
            docker的启动和运行命令都是docker,docker --help能够看到全部的详细参数内容,常见的有如下内容
            docker build 构建镜像,使用Dockerfile
            docker run 运行容器
            docker pull 拉取镜像
            docker push 推送镜像
            docker attach 链接到已经运行的容器上
            docker restart 从新启动容器
            docker rmi 删除镜像
            docker rm 删除容器
            docker stop 中止容器
            docker start 启动容器
            docker save 保存镜像到tar文件,包括历史
            docker load 恢复tar文件到镜像,save的反命令
            docker export 导出镜像最新文件系统到tar文件,没有历史,大小要小于save命令
            docker import 导入tar文件生成镜像,export的反命令
            docker images 显示全部镜像
            docker inspect 显示容器信息
            docker ps 显示运行的容器信息
            docker ps -l 显示最后的容器信息,即便已经中止
 2)配置和目录结构:/root/Dockerfiles下
      ├── mysql
      │   └── Dockerfile
      ├── nginx
      │   ├── default.conf
      │   └── Dockerfile
      └── php
           └── Dockerfile
      mysql基本就是从网上下载的镜像,nginx须要修改配置文件,因此增长了一个default.conf,用来覆盖容器内的配置文件,php容器的配置文件比较简单,不作修改
      /data/html目录保存html和php文件,保存在容器外,这个目录须要映射到nginx和php容器,也定为/data/html
      
      在/data/html下写入三个文件, index.htm info.php mysql.php,分别测试静态文件、PHP文件、Mysql链接
     $ echo '<h1>Hello World!</h1>' > /data/html/index.htm
     $ echo '<?php' > /data/html/info.php
     $ echo '   phpinfo();' >> /data/html/info.php
     $ vim mysql.php
     <?php
     $con = mysql_connect("mysql", "root", "123456");
     if (!$con)
     {
       die('Could not connect: ' . mysql_error());
      }
     $db_selected = mysql_select_db("shiyq",$con);
     mysql_query("set names utf8");
     $sql = "SELECT * from t";
     $result = mysql_query($sql,$con);
     while($row = mysql_fetch_array($result)){
       print_r($row);
     }
     mysql_close($con);
     
     三个容器命名分别为mysql、pfpm、nginx,便于容器链接
 3)mysql, mysql目录下
     $vim Dockerfile
      FROM mysql:5.6
     $docker build -t shiyq/mysql:5.6 .
     Sending build context to Docker daemon 2.048 kB
     Step 1 : FROM mysql:5.6
     5.6: Pulling from library/mysql
     7268d8f794c4: Pull complete
     a3ed95caeb02: Pull complete
     e5a99361f38c: Pull complete
     50aeb59ed433: Pull complete
     5bedb4177480: Pull complete
     366f809ce7dd: Pull complete
     9d8799acdbcd: Pull complete
     647411343675: Pull complete
     a18cdc480897: Pull complete
     45d42e99e3be: Pull complete
     Digest: sha256:8f7fd54e7253031030d060925e4abb78f8387b7417e3afd4b7fde6551cc50255
     Status: Downloaded newer image for mysql:5.6
     ---> f0e9d0beeb6b
     Successfully built f0e9d0beeb6b
     mysql:5.6镜像的Dockerfile能够在https://github.com/docker-library/mysql/blob/ace4c65b8e97f0145616386916aabaec518d4e08/5.6/Dockerfile查看
     $docker images
     REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
     mysql               5.6                 f0e9d0beeb6b        26 hours ago        324.2 MB
     shiyq/mysql         5.6                 f0e9d0beeb6b        26 hours ago        324.2 MB
     能够看出有两个镜像,大小是同样的,缘由是我建立的镜像其实就是彻底的复制官方镜像。

经过Dockerfile能够看出,官方镜像已经用VOLUME指令将mysql数据目录放到了容器外,当容器运行会产生一个随机目录,这个目录能够经过docker inspect看到,不过老是不舒服,这里指定/root/opt/mysql/data来存放数据,即将其映射到/var/lib/mysql,所以,启动容器命令以下php

     $ docker run -it -e MYSQL_ROOT_PASSWORD=123456 -v /root/opt/mysql/data:/var/lib/mysql shiyq/mysql:5.6
     -it表明是交互模式,能够看到输出,主要用于测试,若是正式发布,能够用-d,即后台运行
     -e是环境变量,这个容器启动须要设置root密码,这里设置为123456
     -v是目录映射,将本地的/root/opt/mysql/data映射为/var/lib/mysql
     $docker ps
     CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                     NAMES
     e5c92a9be37c        shiyq/mysql:5.6     "/entrypoint.sh mysql"   4 minutes ago       Up 4 minutes        3306/tcp            modest_jennings
     $ docker inspect e5c92a9be37c        
     这能够看到不少信息,好比ip地址、环境变量、目录映射等,这里的ip地址是172.17.0.2,在宿主机上运行mysql命令
     $ mysql -uroot -p123456 -h 172.17.0.2 -P 3306
     就能够登陆进去了,和正常的mysql数据库没有区别。
     不过这样操做很不方便,须要知道容器的ip地址才能操做,能够将3306端口映射到本地端口,如3307,再次启动容器
    $ docker stop e5c92a9be37c        
    $ docker run -it --name mysql -e MYSQL_ROOT_PASSWORD=123456 -p 3307:3306 -v /root/opt/mysql/data:/var/lib/mysql shiyq/mysql:5.6
    $ mysql -uroot -p123456 -h 127.0.0.1 -P 3307
    mysql> create database shiyq default character set utf8;
    mysql> use shiyq;
    mysql> create table t(id int not null auto_increment primary key,name varchar(20),code varchar(20));
    mysql> insert into t(name,code) values('石永强','shiyq');
4)php-fpm,php目录下
    $ vim Dockerfile
    FROM debian:jessie
    RUN apt-get update
    RUN apt-get install -y php5-fpm php5-mysql php5-mysqlnd
    RUN sed -i "s/^listen = .*$/listen = 9000/g" /etc/php5/fpm/pool.d/www.conf
    RUN sed -i "s/;daemonize = yes/daemonize = no/g" /etc/php5/fpm/php-fpm.conf
    RUN echo "#!/bin/bash" > /root/run.sh
    RUN echo "/usr/sbin/php5-fpm" >> /root/run.sh
    RUN chmod u+x /root/run.sh
    EXPOSE 9000
    CMD ["/root/run.sh"]
    这个Dockerfile是自定义的,采用了debian 8,同时修改了默认的配置文件,将监听设置从unix socket改成端口9000,并禁止其后台运行。
    $ docker build -t shiyq/php-c:5.6-fpm .     
    $ docker run -it --name pfpm --link mysql -p 9001:9000 -v /data/html:/data/html shiyq/php-c:5.6-fpm 
    题外话:官方镜像没法使用,不能访问Mysql,因此只好自定义
5)nginx, nginx目录下
    $ vim Dockerfile
     FROM nginx:1.9
     $ docker build -t shiyq/nginx:1.9 .
     Sending build context to Docker daemon  2.56 kB
     Step 1 : FROM nginx:1.9
     1.9: Pulling from library/nginx
     7268d8f794c4: Already exists
     a3ed95caeb02: Pull complete
     455603953088: Pull complete
     7648078317e7: Pull complete
     Digest: sha256:3feee5ea8dd682950c9873e8c1d9d689b7d257f1ee8f82a11c484cee9dd6c446
     Status: Downloaded newer image for nginx:1.9
      ---> 574907042fd7
     Successfully built 574907042fd7
     $ docker run -it shiyq/nginx:1.9 /bin/bash
     root@1ffba22d4129:/# cat /etc/nginx/conf.d/default.conf
     server {
         listen       80;
         server_name  localhost;
         #charset koi8-r;
         #access_log  /var/log/nginx/log/host.access.log  main;
         location / {
             root   /usr/share/nginx/html;
             index  index.html index.htm;
         }
         #error_page  404              /404.html;
         # redirect server error pages to the static page /50x.html          #
         error_page   500 502 503 504  /50x.html;
         location = /50x.html {
             root   /usr/share/nginx/html;
         }
         # proxy the PHP scripts to Apache listening on 127.0.0.1:80
         #
         #location ~ \.php$ {
         #    proxy_pass   http://127.0.0.1;
         #}
         # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
         #
         #location ~ \.php$ {
         #    root           html;
         #    fastcgi_pass   127.0.0.1:9000;
         #    fastcgi_index  index.php;
         #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
         #    include        fastcgi_params;
         #}
         # deny access to .htaccess files, if Apache's document root
         # concurs with nginx's one
         #
         #location ~ /\.ht {
         #    deny  all;
         #}
     }
     将容器的default.conf的内容复制到本地的default.conf,并修改以下
     server {
         listen       80;
         server_name  localhost;
         #charset koi8-r;
         #access_log  /var/log/nginx/log/host.access.log  main;
         location / {
             root   /data/html;
             index  index.html index.htm index.php;
         }
         #error_page  404              /404.html;
         # redirect server error pages to the static page /50x.html
         #
         error_page   500 502 503 504  /50x.html;
         location = /50x.html {
             root   /data/html;
         }
         # proxy the PHP scripts to Apache listening on 127.0.0.1:80
         #
         #location ~ \.php$ {
         #    proxy_pass   http://127.0.0.1;
         #}
         # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
         #
         location ~ \.php$ {
              root           /data/html;
              fastcgi_pass   pfpm:9000;
              fastcgi_index  index.php;
              fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
              include        fastcgi_params;
         }
         # deny access to .htaccess files, if Apache's document root
         # concurs with nginx's one
         #
         #location ~ /\.ht {
         #    deny  all;
         #}
     }
     增长和修改的内容已经黑体标出,主要是修改了默认的目录为/data/html,另外打开了php-fpm,用来运行php程序,不过须要注意的是这里的主机名用的pfpm,这是php-fpm容器使用的名字,最后会采用容器链接的方式链接php-fpm,一样php-fpm也会用一样的方式链接mysql容器。

 

     $  docker run -it --name nginx --link pfpm -p 800:80 -v /data/html:/data/html -v /root/Dockerfiles/nginx/default.conf:/etc/nginx/conf.d/default.conf shiyq/nginx:1.9
 6)运行
     $ docker ps
     CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                            NAMES
     e33a1cc68794        shiyq/nginx:1.9     "nginx -g 'daemon off"   2 minutes ago       Up 2 minutes        443/tcp, 0.0.0.0:800->80/tcp   nginx
     40c3ac953494        shiyq/php:5.6-fpm   "php-fpm"                4 minutes ago       Up 4 minutes        0.0.0.0:9001->9000/tcp         pfpm
     3228d0f7ce7e        shiyq/mysql:5.6     "/entrypoint.sh mysql"   12 minutes ago      Up 12 minutes       0.0.0.0:3307->3306/tcp         mysql
     能够看到启动了3个容器,nginx80端口映射为宿主机800,链接到php容器,php-fpm的9000端口映射为9001端口,链接到mysql容器,mysql容器的3306映射为3307端口
     $ curl localhost:800

Hello World!

     $ curl localhost:800/mysql.php
     Array
     (
          [0] => 1
          [id] => 1
          [1] => 石永强
          [name] => 石永强
          [2] => shiyq
          [code] => shiyq
      )
 7)脚本
     $ vim start_npm.sh
     docker rm -f $(docker ps -a -q -f name="mysql|pfpm|nginx");
     docker run -it -d --name mysql -e MYSQL_ROOT_PASSWORD=123456 -p 3307:3306 -v /root/opt/mysql/data:/var/lib/mysql shiyq/mysql:5.6;
     docker run -it -d --name pfpm --link mysql -p 9001:9000 -v /data/html:/data/html shiyq/php-c:5.6-fpm;
     docker run -it -d --name nginx --link pfpm -p 800:80 -v /data/html:/data/html -v /root/Dockerfiles/nginx/default.conf:/etc/nginx/conf.d/default.conf shiyq/nginx:1.9;
     $./start_npm.sh 能够自动删除容器,并重启容器
8)和windows共享文件
     a)创建e:/data/html目录
     b)虚拟机共享目录: 虚拟机->控制->设置->共享文件夹,固定分配,选择共享名称为data_html,自动加载和固定分配勾选
     c)安装加强功能:虚拟机->设备->安装加强功能,这会在虚拟机上挂载一个硬盘
        $ mkdir /mnt/cdrom
        $ mount -t auto -r /dev/cdrom /mnt/cdrom
        $ yum install bzip2 kernel-devel
        $ cd /mnt/cdrom
        $ ./VBoxLinuxAdditions.run
     d) 挂载到/data/html
        $  mount -t vboxsf data_html /data/html
        $ curl localhost:800
        Array
        (
           [0] => 1
           [id] => 1
           [1] => 石永强
           [name] => 石永强
           [2] => shiyq
           [code] => shiyq
         )
        
     e)自动挂载
     $ chmod +x /etc/rc.local
     $ echo 'mount -t vboxsf data_html /data/html' >> /etc/rc.local
     f)重启机器,能够看到目录已经挂载,
     $ /root/Dockerfiles/start_npm.sh
     $ curl localhost:800
     Array
    (
        [0] => 1
        [id] => 1
        [1] => 石永强
        [name] => 石永强
        [2] => shiyq
        [code] => shiyq
    )
   Array
   (
       [0] => 2
       [id] => 2
       [1] => 刘万斌
       [name] => 刘万斌
       [2] => liuwb
       [code] => liuwb
    )
    到此就能够和windows共享文件,在windows上开发,在docker中运行,若是用文本编辑器写程序,基本就能够了,可是用ide,就有些麻烦了,须要本机也安装php,要求版本一致,并不容易,尤为是windows上的php很难找到低版本的,不过好在能够在提交测试前就能够发现问题。
    未解决的问题
    1)网络地址问题:手动配置和工具配置。
相关文章
相关标签/搜索