<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>DevOps技术分享 &#187; Docker</title>
	<atom:link href="http://www.showerlee.com/archives/tag/docker/feed" rel="self" type="application/rss+xml" />
	<link>http://www.showerlee.com</link>
	<description>与你共同学习运维开发</description>
	<lastBuildDate>Mon, 19 Oct 2020 05:51:41 +0000</lastBuildDate>
	<language>zh-CN</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.6</generator>
		<item>
		<title>Mac+Docker+Ansible部署WordPress Application</title>
		<link>http://www.showerlee.com/archives/1938</link>
		<comments>http://www.showerlee.com/archives/1938#comments</comments>
		<pubDate>Tue, 06 Dec 2016 09:42:37 +0000</pubDate>
		<dc:creator>showerlee</dc:creator>
				<category><![CDATA[Ansible]]></category>
		<category><![CDATA[Docker]]></category>

		<guid isPermaLink="false">http://www.showerlee.com/?p=1938</guid>
		<description><![CDATA[很久没有更新了，今天给大家在这里推荐使用Docker部署Wordpress Application Docke [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>
	很久没有更新了，今天给大家在这里推荐使用<a href="http://www.showerlee.com/archives/tag/docker" title="查看Docker中的全部文章" class="tag_link">Docker</a>部署Wordpress Application
</p>
<p>
	<a href="http://www.showerlee.com/archives/tag/docker" title="查看Docker中的全部文章" class="tag_link">Docker</a>就不多介绍了，大家可以理解为是他是一个虚拟集装箱，将原来以服务器为基础单元的集群，细化到以每个服务进程为单元。这样的优点在于：
</p>
<p>
	1. 隔离开发环境和具体可执行进程，可跨平台跨主机使用，统一开发环境
</p>
<p>
	2. 节约时间成本，硬件成本，秒级别快速部署启动
</p>
<p>
	3. 支持持续集成，可利用相关部署工具(<a href="http://www.showerlee.com/archives/tag/ansible" title="查看Ansible中的全部文章" class="tag_link">Ansible</a>, saltstack)进行快速部署
</p>
<p>
	4. 可作为轻量级别主机或节点部署应用
</p>
<p>
	5. 未来可能代替虚拟机的虚拟容器
</p>
<p>
	
</p>
<p>
	最后利用<a href="http://www.showerlee.com/archives/tag/ansible" title="查看Ansible中的全部文章" class="tag_link">Ansible</a>去对<a href="http://www.showerlee.com/archives/tag/docker" title="查看Docker中的全部文章" class="tag_link">Docker</a>容器进行具体服务的部署，最大限度的体现轻量级，统一开发部署环境的好处。
</p>
<p>
	
</p>
<p>
	在部署之前首先给大家介绍一下我的部署结构:
</p>
<p>
	<span style="color:#E53333;">dockerfiles</span><br />
<span style="color:#E53333;"> ├── mariadb</span><br />
<span style="color:#E53333;"> │ &nbsp; ├── <a href="http://www.showerlee.com/archives/tag/docker" title="查看Docker中的全部文章" class="tag_link">Docker</a>file</span><br />
<span style="color:#E53333;"> │ &nbsp; ├── ansible</span><br />
<span style="color:#E53333;"> │ &nbsp; │ &nbsp; ├── mariadb-install-container.yml</span><br />
<span style="color:#E53333;"> │ &nbsp; │ &nbsp; ├── mariadb.sh</span><br />
<span style="color:#E53333;"> │ &nbsp; │ &nbsp; ├── mariadb.sql</span><br />
<span style="color:#E53333;"> │ &nbsp; │ &nbsp; └── my.cnf</span><br />
<span style="color:#E53333;"> │ &nbsp; └── run.sh</span><br />
<span style="color:#E53333;"> ├── nginx</span><br />
<span style="color:#E53333;"> │ &nbsp; ├── <a href="http://www.showerlee.com/archives/tag/docker" title="查看Docker中的全部文章" class="tag_link">Docker</a>file</span><br />
<span style="color:#E53333;"> │ &nbsp; ├── ansible</span><br />
<span style="color:#E53333;"> │ &nbsp; │ &nbsp; ├── default.conf</span><br />
<span style="color:#E53333;"> │ &nbsp; │ &nbsp; ├── nginx-container.yml</span><br />
<span style="color:#E53333;"> │ &nbsp; │ &nbsp; └── nginx.conf</span><br />
<span style="color:#E53333;"> │ &nbsp; └── run.sh</span><br />
<span style="color:#E53333;"> └── php</span><br />
<span style="color:#E53333;"> &nbsp; &nbsp; ├── <a href="http://www.showerlee.com/archives/tag/docker" title="查看Docker中的全部文章" class="tag_link">Docker</a>file</span><br />
<span style="color:#E53333;"> &nbsp; &nbsp; ├── ansible</span><br />
<span style="color:#E53333;"> &nbsp; &nbsp; │ &nbsp; ├── info.php</span><br />
<span style="color:#E53333;"> &nbsp; &nbsp; │ &nbsp; ├── php-container.yml</span><br />
<span style="color:#E53333;"> &nbsp; &nbsp; │ &nbsp; ├── test-db-conn.php</span><br />
<span style="color:#E53333;"> &nbsp; &nbsp; │ &nbsp; ├── wp-config.php</span><br />
<span style="color:#E53333;"> &nbsp; &nbsp; │ &nbsp; └── <a href="http://www.conf" rel="nofollow">http://www.conf</a></span><br />
<span style="color:#E53333;"> &nbsp; &nbsp; └── run.sh</span>
</p>
<p>
	<a href="http://www.showerlee.com/archives/tag/docker" title="查看Docker中的全部文章" class="tag_link">Docker</a>files主目录下面分别是3个服务所对应的目录，每个目录大致分为<a href="http://www.showerlee.com/archives/tag/docker" title="查看Docker中的全部文章" class="tag_link">Docker</a>file配置文件, ansible目录，以及run.sh
</p>
<p>
	<a href="http://www.showerlee.com/archives/tag/docker" title="查看Docker中的全部文章" class="tag_link">Docker</a>file这个大家都清楚，用来Build容器镜像的配置脚本。
</p>
<p>
	ansible目录下保存需要在容器内使用到的ansible playbook相应配置文件。
</p>
<p>
	run.sh则是创建和运行容器的启动脚本，我们分别去执行对应目录的执行脚本用来构建Docker容器所对应的服务。
</p>
<p>
	
</p>
<p>
	这里给大家提供一个我的gitlab私人仓库的链接，方便大家去下载这个部署脚本：
</p>
<p>
	<a href="https://git.showerlee.com/showerlee/ansible-docker-wp" target="_blank">https://git.showerlee.com/showerlee/ansible-docker-wp</a>
</p>
<p>
	
</p>
<p>
	大家如果想对Docker和<a href="http://www.showerlee.com/archives/tag/ansible" title="查看Ansible中的全部文章" class="tag_link">Ansible</a>有不太明白的地方可以先阅读我之前写的文章。
</p>
<p>
	Docker:&nbsp;<a href="http://www.showerlee.com/archives/1758" target="_blank">http://www.showerlee.com/archives/1758</a>
</p>
<p>
	<a href="http://www.showerlee.com/archives/tag/ansible" title="查看Ansible中的全部文章" class="tag_link">Ansible</a>: <a href="http://www.showerlee.com/archives/1649" target="_blank">http://www.showerlee.com/archives/1649</a>
</p>
<p>
	
</p>
<p>
	<strong><span style="color:#337FE5;font-size:16px;">一.环境部署</span></strong>
</p>
<p>
	<span style="color:#337FE5;">Local system: &nbsp;MAC OS X 10.12.1</span><br />
<span style="color:#337FE5;">Docker: &nbsp; Docker 1.12.3</span>
</p>
<p>
	<span style="color:#E53333;">Tip: 这里说明一下，较早版本的Docker若在非Linux内核下去安装需要去配合安装virtualbox虚拟机才能正常使用，这里我们使用的最新版本Docker配合MAC OS 10.12.1最新开放出来的内核接口，可无需调用额外虚拟机直接安装使用即可。</span>
</p>
<p>
	
</p>
<p>
	<strong><span style="color:#337FE5;font-size:16px;">二.Docker部署</span></strong>
</p>
<p>
	<span style="font-size:14px;color:#337FE5;"><strong>Mariadb container</strong></span>
</p>
<p>
	Mariadb是Mysql在CentOS7上的一个开源分支, 大家可以理解就是一个mysql. 这里首先我们为什么先去部署并启动Mariadb, 是因为我们后面启动Docker时会用到它的一个Link参数，这个参数不仅保证两台容器会安全的利用这个Link去传输数据，而且还会在被Link主机内创建一个host记录，方便我们直接用FQDN名去访问相应主机。
</p>
<p>
	
</p>
<p>
	<span style="color:#337FE5;">Dockerfile</span>
</p>
<pre class="prettyprint lang-bsh">FROM ansible/centos7-ansible/:stable

ADD ansible /data/ansible

WORKDIR /data/ansible

RUN ansible-playbook mariadb-install-container.yml -c local

# Initialize and start mariadb
RUN chmod +x mariadb.sh

CMD ["./mariadb.sh"]

EXPOSE 3306</pre>
<p>这里简单来说就是下载集成Ansible的CentOS7容器镜像，并将ansible playbook及相应配置文件复制到容器内去部署MariaDB初始环境，最终启动服务，并开启3306DB端口.</p>
<p>
	
</p>
<p>
	<span style="color:#337FE5;">ansible/mariadb-install-container.yml</span>
</p>
<pre class="prettyprint">- name: Install Mariadb container
  hosts: local
  vars:
    conf_path: /etc/my.cnf
    src_socket: /data/mariadb_data/mysql.sock
    link_socket: /var/lib/mysql/mysql.sock
    user: mysql
  tasks:
  - name: Install epel-release package
    yum: name=epel-release state=latest

  - name: Install required packages
    yum: name={{ item }} state=latest
    with_items:
      - net-tools
      - lsof 
      - nmap
      - mariadb-server
      - MySQL-python

  - name: Copy mariadb conf
    copy: src=my.cnf dest={{ conf_path }} mode=0644

  - name: Link mysql socket
    file: 
      src={{ src_socket }} dest={{ link_socket }} state=link force=yes</pre>
<p>这里是ansible playbook, 基本上就是利用ansible本地安装Epel源以及Mariadb相应的安装包，然后进行DB的相关配置。</p>
<p>
	
</p>
<p>
	<span style="color:#337FE5;">ansible/mariadb.sh</span>
</p>
<pre class="prettyprint lang-bsh">#!/bin/sh
 chown -R mysql:mysql /var/lib/mysql

 mysql_install_db --user=mysql --datadir=/data/mariadb_data &gt; /dev/null

 mysqld_safe &amp;

 sleep 5s

 mysql -v &lt; mariadb.sql

 sleep 5s

 ps -wef | grep mysql | grep -v grep | awk '{print $2}' | xargs kill -9

 mysqld_safe --user mysql</pre>
<p>这里是对Mariadb进行初始化安装，并使用sql脚本更改root密码及相应权限和创建Wordpress数据库，最终重启DB服务。</p>
<p>
	
</p>
<p>
	<span style="color:#337FE5;">ansible/Mariadb.sql</span>
</p>
<pre class="prettyprint">USE mysql;
 GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' WITH GRANT OPTION;
 FLUSH PRIVILEGES;
 UPDATE user SET password=PASSWORD("123456") WHERE user='root';
 FLUSH PRIVILEGES;
 CREATE DATABASE wordpress;
 FLUSH PRIVILEGES;</pre>
<p><span style="color:#337FE5;">ansible/my.cnf</span> </p>
<pre class="prettyprint">[mysqld]
datadir=/data/mariadb_data
socket=/data/mariadb_data/mysql.sock
port=3306
bind-address = 0.0.0.0

# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
# Settings user and group are ignored when systemd is used.
# If you need to run mysqld under a different user or group,
# customize your systemd unit file for mariadb according to the
# instructions in <a href="http://fedoraproject.org/wiki/Systemd" rel="nofollow">http://fedoraproject.org/wiki/Systemd</a>

[mysqld_safe]
log-error=/var/log/mariadb/mariadb.log
pid-file=/var/run/mariadb/mariadb.pid

#
# include all files from the config directory
#
!includedir /etc/my.cnf.d</pre>
<p>Mariadb的DB配置.</p>
<p>
	
</p>
<p>
	<span style="color:#337FE5;">run.sh</span>
</p>
<pre class="prettyprint lang-bsh">#/bin/bash

IMAGE="leon/mariadb"
Container="mariadb"

docker build -t ${IMAGE} .

docker run -d -p 3306:3306 --name ${Container} ${IMAGE}</pre>
<p>最终我们使用docker build去创建一个基于Dockerfile配置的MariaDB容器镜像，并用docker run去启动这个容器镜像。</p>
<p>
	<span style="color:#E53333;">Tip: -d为后台启动容器，-p为打开端口，--name 为创建容器名，-t为打一个镜像标签。</span>
</p>
<p>
	
</p>
<p>
	
</p>
<p>
	<span style="color:#337FE5;font-size:14px;"><strong>PHP container</strong></span>
</p>
<p>
	接下来我们会部署启动php-fpm服务，作为解析Wordpress网站的php服务, 它会开启9000端口，方便后面的nginx container去进行反向连接。
</p>
<p>
	
</p>
<p>
	<span style="color:#337FE5;">Dockerfile</span>
</p>
<pre class="prettyprint lang-bsh">FROM ansible/centos7-ansible:stable

ADD ansible /data/ansible

WORKDIR /data/ansible

RUN ansible-playbook php-container.yml -c local

# Add the volume to php application
VOLUME ["/data/app"]

# CMD ["php-fpm", "--nodaemonize"]
ENTRYPOINT ["/usr/sbin/php-fpm", "-F"]

EXPOSE 9000</pre>
<p>
	这里的配置基本上和MariaDB类似，区别在于我们会在这里去创建一个与nginx共同使用的共享网站目录，里面会保存Wordpress源代码和相关php测试文件。
</p>
<p>
	
</p>
<p>
	<span style="color:#337FE5;">ansible/php-container.yml</span>
</p>
<pre class="prettyprint">- name: Create PHP container
  hosts: local
  vars:
    app_dir: /data/app
    src_dir: /data/src
    phpfpm_path: /etc/php-fpm.d/www.conf
    info_path: /data/app/info.php
    test_path: /data/app/test-db-conn.php
    wp_url: <a href="https://cn.wordpress.org/wordpress-4.5.3-zh_CN.tar.gz" rel="nofollow">https://cn.wordpress.org/wordpress-4.5.3-zh_CN.tar.gz</a>
    wp_config: /data/app/wp-config.php
  tasks:
  - name: Install epel-release packages
    yum: name=epel-release state=latest 

  - name: Install required packages
    yum: name={{ item }} state=latest
    with_items:
      - net-tools
      - lsof
      - nmap
      - unzip
      - mariadb

  - name: Install php packages
    yum: name={{ item }} state=latest
    with_items:
      - php
      - php-mysql
      - php-fpm
      - php-gd
      - php-mbstring

  - name: Create dir
    file: path={{ item }} state=directory mode=0755
    with_items:
      - "{{ app_dir }}"
      - "{{ src_dir }}"

  - name: Unpack WP package
    unarchive: src={{ wp_url }} dest={{ src_dir }} remote_src=yes

  - name: Move WP source code to app_dir
    shell: "shopt -s dotglob &amp;&amp; mv {{ src_dir }}/wordpress/* {{ app_dir }}" 

  - name: Copy wp configuration
    copy: src=wp-config.php dest={{ wp_config }}

  - name: Copy php info page
    copy: src=info.php dest={{ info_path }} mode=0755

  - name: Copy test-db-conn page
    copy: src=test-db-conn.php dest={{ test_path }} mode=0755

  - name: Copy nginx configuration
    copy: src=www.conf dest={{ phpfpm_path }} mode=0755</pre>
<p>
	这里playbook配置内容较多，不过基本上就是安装php-fpm以及相应安装包，配置php-fpm配置项，并下载Wordpress源代码并将DB信息写入WP配置文件，复制php测试脚本等。
</p>
<p>
	
</p>
<p>
	<span style="color:#337FE5;">ansible/info.php</span>
</p>
<pre class="prettyprint">&lt;?php
phpinfo();
?&gt;
</pre>
<p><span style="color:#337FE5;">ansible/test-db-conn.php</span> </p>
<pre class="prettyprint">&lt;html&gt;&lt;body&gt;&lt;h1&gt;The page to test Mariadb connection.&lt;/h1&gt;&lt;/body&gt;&lt;/html&gt;
&lt;?php
 $conn=mysql_connect('mariadb','root','123456');
 if ($conn)
   echo "&lt;h2&gt;Success...&lt;/h2&gt;";
 else
   echo "&lt;h2&gt;Failure...&lt;/h2&gt;";
 
?&gt;
</pre>
<p><span style="color:#337FE5;">ansible/wp-config.php</span> </p>
<pre class="prettyprint lang-php">&lt;?php
/**
 * WordPress基础配置文件。
 *
 * 这个文件被安装程序用于自动生成wp-config.php配置文件，
 * 您可以不使用网站，您需要手动复制这个文件，
 * 并重命名为“wp-config.php”，然后填入相关信息。
 *
 * 本文件包含以下配置选项：
 *
 * * MySQL设置
 * * 密钥
 * * 数据库表名前缀
 * * ABSPATH
 *
 * @link <a href="https://codex.wordpress.org/zh-cn:%E7%BC%96%E8%BE%91_wp-config.php" rel="nofollow">https://codex.wordpress.org/zh-cn:%E7%BC%96%E8%BE%91_wp-config.php</a>
 *
 * @package WordPress
 */

// ** MySQL 设置 - 具体信息来自您正在使用的主机 ** //
/** WordPress数据库的名称 */
define('DB_NAME', 'wordpress');

/** MySQL数据库用户名 */
define('DB_USER', 'root');

/** MySQL数据库密码 */
define('DB_PASSWORD', '123456');

/** MySQL主机 */
define('DB_HOST', 'mariadb');

/** 创建数据表时默认的文字编码 */
define('DB_CHARSET', 'utf8');

/** 数据库整理类型。如不确定请勿更改 */
define('DB_COLLATE', '');

/**#@+
 * 身份认证密钥与盐。
 *
 * 修改为任意独一无二的字串！
 * 或者直接访问{@link <a href="https://api.wordpress.org/secret-key/1.1/salt/" rel="nofollow">https://api.wordpress.org/secret-key/1.1/salt/</a>
 * WordPress.org密钥生成服务}
 * 任何修改都会导致所有cookies失效，所有用户将必须重新登录。
 *
 * @since 2.6.0
 */
define('AUTH_KEY',         'put your unique phrase here');
define('SECURE_AUTH_KEY',  'put your unique phrase here');
define('LOGGED_IN_KEY',    'put your unique phrase here');
define('NONCE_KEY',        'put your unique phrase here');
define('AUTH_SALT',        'put your unique phrase here');
define('SECURE_AUTH_SALT', 'put your unique phrase here');
define('LOGGED_IN_SALT',   'put your unique phrase here');
define('NONCE_SALT',       'put your unique phrase here');

/**#@-*/

/**
 * WordPress数据表前缀。
 *
 * 如果您有在同一数据库内安装多个WordPress的需求，请为每个WordPress设置
 * 不同的数据表前缀。前缀名只能为数字、字母加下划线。
 */
$table_prefix  = 'wp_';

/**
 * 开发者专用：WordPress调试模式。
 *
 * 将这个值改为true，WordPress将显示所有用于开发的提示。
 * 强烈建议插件开发者在开发环境中启用WP_DEBUG。
 *
 * 要获取其他能用于调试的信息，请访问Codex。
 *
 * @link <a href="https://codex.wordpress.org/Debugging_in_WordPress" rel="nofollow">https://codex.wordpress.org/Debugging_in_WordPress</a>
 */
define('WP_DEBUG', false);

/**
 * zh_CN本地化设置：启用ICP备案号显示
 *
 * 可在设置→常规中修改。
 * 如需禁用，请移除或注释掉本行。
 */
define('WP_ZH_CN_ICP_NUM', true);

/* 好了！请不要再继续编辑。请保存本文件。使用愉快！ */

/** WordPress目录的绝对路径。 */
if ( !defined('ABSPATH') )
	define('ABSPATH', dirname(__FILE__) . '/');

/** 设置WordPress变量和包含文件。 */
require_once(ABSPATH . 'wp-settings.php');</pre>
<p><span style="color:#337FE5;">ansible/www.conf</span> </p>
<pre class="prettyprint">; Start a new pool named 'www'.
[www]

; The address on which to accept FastCGI requests.
; Valid syntaxes are:
;   'ip.add.re.ss:port'    - to listen on a TCP socket to a specific address on
;                            a specific port;
;   'port'                 - to listen on a TCP socket to all addresses on a
;                            specific port;
;   '/path/to/unix/socket' - to listen on a unix socket.
; Note: This value is mandatory.
listen = 0.0.0.0:9000

; Set listen(2) backlog. A value of '-1' means unlimited.
; Default Value: -1
;listen.backlog = -1
 
; List of ipv4 addresses of FastCGI clients which are allowed to connect.
; Equivalent to the FCGI_WEB_SERVER_ADDRS environment variable in the original
; PHP FCGI (5.2.2+). Makes sense only with a tcp listening socket. Each address
; must be separated by a comma. If this value is left blank, connections will be
; accepted from any ip address.
; Default Value: any
;listen.allowed_clients = any

; Set permissions for unix socket, if one is used. In Linux, read/write
; permissions must be set in order to allow connections from a web server. Many
; BSD-derived systems allow connections regardless of permissions. 
; Default Values: user and group are set as the running user
;                 mode is set to 0666
listen.owner = nobody
listen.group = nobody
listen.mode = 0666

; Unix user/group of processes
; Note: The user is mandatory. If the group is not set, the default user's group
;       will be used.
; RPM: apache Choosed to be able to access some dir as httpd
user = nobody
; RPM: Keep a group allowed to write in log dir.
group = nobody

; Choose how the process manager will control the number of child processes.
; Possible Values:
;   static  - a fixed number (pm.max_children) of child processes;
;   dynamic - the number of child processes are set dynamically based on the
;             following directives:
;             pm.max_children      - the maximum number of children that can
;                                    be alive at the same time.
;             pm.start_servers     - the number of children created on startup.
;             pm.min_spare_servers - the minimum number of children in 'idle'
;                                    state (waiting to process). If the number
;                                    of 'idle' processes is less than this
;                                    number then some children will be created.
;             pm.max_spare_servers - the maximum number of children in 'idle'
;                                    state (waiting to process). If the number
;                                    of 'idle' processes is greater than this
;                                    number then some children will be killed.
; Note: This value is mandatory.
pm = dynamic

; The number of child processes to be created when pm is set to 'static' and the
; maximum number of child processes to be created when pm is set to 'dynamic'.
; This value sets the limit on the number of simultaneous requests that will be
; served. Equivalent to the ApacheMaxClients directive with mpm_prefork.
; Equivalent to the PHP_FCGI_CHILDREN environment variable in the original PHP
; CGI.
; Note: Used when pm is set to either 'static' or 'dynamic'
; Note: This value is mandatory.
pm.max_children = 5

; The number of child processes created on startup.
; Note: Used only when pm is set to 'dynamic'
; Default Value: min_spare_servers + (max_spare_servers - min_spare_servers) / 2
pm.start_servers = 2

; The desired minimum number of idle server processes.
; Note: Used only when pm is set to 'dynamic'
; Note: Mandatory when pm is set to 'dynamic'
pm.min_spare_servers = 1

; The desired maximum number of idle server processes.
; Note: Used only when pm is set to 'dynamic'
; Note: Mandatory when pm is set to 'dynamic'
pm.max_spare_servers = 3
 
; The number of requests each child process should execute before respawning.
; This can be useful to work around memory leaks in 3rd party libraries. For
; endless request processing specify '0'. Equivalent to PHP_FCGI_MAX_REQUESTS.
; Default Value: 0
;pm.max_requests = 500

; The URI to view the FPM status page. If this value is not set, no URI will be
; recognized as a status page. By default, the status page shows the following
; information:
;   accepted conn    - the number of request accepted by the pool;
;   pool             - the name of the pool;
;   process manager  - static or dynamic;
;   idle processes   - the number of idle processes;
;   active processes - the number of active processes;
;   total processes  - the number of idle + active processes.
; The values of 'idle processes', 'active processes' and 'total processes' are
; updated each second. The value of 'accepted conn' is updated in real time.
; Example output:
;   accepted conn:   12073
;   pool:             www
;   process manager:  static
;   idle processes:   35
;   active processes: 65
;   total processes:  100
; By default the status page output is formatted as text/plain. Passing either
; 'html' or 'json' as a query string will return the corresponding output
; syntax. Example:
;   <a href="http://www.foo.bar/status" rel="nofollow">http://www.foo.bar/status</a>
;   <a href="http://www.foo.bar/status?json" rel="nofollow">http://www.foo.bar/status?json</a>
;   <a href="http://www.foo.bar/status?html" rel="nofollow">http://www.foo.bar/status?html</a>
; Note: The value must start with a leading slash (/). The value can be
;       anything, but it may not be a good idea to use the .php extension or it
;       may conflict with a real PHP file.
; Default Value: not set 
;pm.status_path = /status
 
; The ping URI to call the monitoring page of FPM. If this value is not set, no
; URI will be recognized as a ping page. This could be used to test from outside
; that FPM is alive and responding, or to
; - create a graph of FPM availability (rrd or such);
; - remove a server from a group if it is not responding (load balancing);
; - trigger alerts for the operating team (24/7).
; Note: The value must start with a leading slash (/). The value can be
;       anything, but it may not be a good idea to use the .php extension or it
;       may conflict with a real PHP file.
; Default Value: not set
;ping.path = /ping

; This directive may be used to customize the response of a ping request. The
; response is formatted as text/plain with a 200 response code.
; Default Value: pong
;ping.response = pong
 
; The timeout for serving a single request after which the worker process will
; be killed. This option should be used when the 'max_execution_time' ini option
; does not stop script execution for some reason. A value of '0' means 'off'.
; Available units: s(econds)(default), m(inutes), h(ours), or d(ays)
; Default Value: 0
;request_terminate_timeout = 0
 
; The timeout for serving a single request after which a PHP backtrace will be
; dumped to the 'slowlog' file. A value of '0s' means 'off'.
; Available units: s(econds)(default), m(inutes), h(ours), or d(ays)
; Default Value: 0
;request_slowlog_timeout = 0
 
; The log file for slow requests
; Default Value: not set
; Note: slowlog is mandatory if request_slowlog_timeout is set
slowlog = /var/log/php-fpm/www-slow.log
 
; Set open file descriptor rlimit.
; Default Value: system defined value
;rlimit_files = 1024
 
; Set max core size rlimit.
; Possible Values: 'unlimited' or an integer greater or equal to 0
; Default Value: system defined value
;rlimit_core = 0
 
; Chroot to this directory at the start. This value must be defined as an
; absolute path. When this value is not set, chroot is not used.
; Note: chrooting is a great security feature and should be used whenever 
;       possible. However, all PHP paths will be relative to the chroot
;       (error_log, sessions.save_path, ...).
; Default Value: not set
;chroot = 
 
; Chdir to this directory at the start. This value must be an absolute path.
; Default Value: current directory or / when chroot
;chdir = /var/www
 
; Redirect worker stdout and stderr into main error log. If not set, stdout and
; stderr will be redirected to /dev/null according to FastCGI specs.
; Default Value: no
;catch_workers_output = yes
 
; Limits the extensions of the main script FPM will allow to parse. This can
; prevent configuration mistakes on the web server side. You should only limit
; FPM to .php extensions to prevent malicious users to use other extensions to
; exectute php code.
; Note: set an empty value to allow all extensions.
; Default Value: .php
;security.limit_extensions = .php .php3 .php4 .php5

; Pass environment variables like LD_LIBRARY_PATH. All $VARIABLEs are taken from
; the current environment.
; Default Value: clean env
;env[HOSTNAME] = $HOSTNAME
;env[PATH] = /usr/local/bin:/usr/bin:/bin
;env[TMP] = /tmp
;env[TMPDIR] = /tmp
;env[TEMP] = /tmp

; Additional php.ini defines, specific to this pool of workers. These settings
; overwrite the values previously defined in the php.ini. The directives are the
; same as the PHP SAPI:
;   php_value/php_flag             - you can set classic ini defines which can
;                                    be overwritten from PHP call 'ini_set'. 
;   php_admin_value/php_admin_flag - these directives won't be overwritten by
;                                     PHP call 'ini_set'
; For php_*flag, valid values are on, off, 1, 0, true, false, yes or no.

; Defining 'extension' will load the corresponding shared extension from
; extension_dir. Defining 'disable_functions' or 'disable_classes' will not
; overwrite previously defined php.ini values, but will append the new value
; instead.

; Default Value: nothing is defined by default except the values in php.ini and
;                specified at startup with the -d argument
;php_admin_value[sendmail_path] = /usr/sbin/sendmail -t -i -f <a href="mailto:www@my.domain.com">www@my.domain.com</a>
;php_flag[display_errors] = off
php_admin_value[error_log] = /var/log/php-fpm/www-error.log
php_admin_flag[log_errors] = on
;php_admin_value[memory_limit] = 128M

; Set session path to a directory owned by process user
php_value[session.save_handler] = files
php_value[session.save_path] = /var/lib/php/session</pre>
<p>
	<span style="color:#337FE5;">run.sh</span>
</p>
<pre class="prettyprint lang-bsh">#/bin/bash

IMAGE="leon/php"
Container="php"
Link="mariadb"

docker build -t ${IMAGE} .

docker run -d -p 9000:9000 --name ${Container} --link ${Link}:${Link} ${IMAGE}</pre>
<p>
	这里去创建PHP并启动镜像，需要提到这里的link就是文章开头说到的需要与DB进行安全传输，并在php容器内创建一个DB的host记录。
</p>
<p>
	我们可以使用这个命令去进入容器，查看该记录。
</p>
<pre class="prettyprint lang-bsh"># docker exec -it php bash
[root@7e6188415cb2 ansible]# cat /etc/hosts
127.0.0.1      	localhost
::1    	localhost ip6-localhost ip6-loopback
fe00::0	ip6-localnet
ff00::0	ip6-mcastprefix
ff02::1	ip6-allnodes
ff02::2	ip6-allrouters
172.17.0.2     mariadb 29ae9593fbfc
172.17.0.3     7e6188415cb2</pre>
<p><span style="color:#E53333;">Tip: 这里可以看到mariadb的内网ip为172.17.0.2, php-fpm的为172.17.0.3, 我们MAC本机作为Docker主机与容器间会进行DNAT通信，容器因为在同一内网，可自由通信，前提是需要在创建和启动镜像前打开相应服务端口。</span> </p>
<p>
	
</p>
<p>
	<span style="color:#E53333;"><br />
</span>
</p>
<p>
	<span style="color:#337FE5;font-size:14px;"><strong>Nginx container</strong></span>
</p>
<p>
	这里最终我们会利用Nginx作为一个反向代理，配置www.example.com去访问我们的PHP容器下的Wordpress页面.
</p>
<p>
	
</p>
<p>
	<span style="color:#337FE5;">Dockerfile</span>
</p>
<pre class="prettyprint lang-bsh">FROM ansible/centos7-ansible/epel:stable

ADD ansible /data/ansible

WORKDIR /data/ansible

RUN ansible-playbook nginx-container.yml -c local

VOLUME ["/data/app"]

# CMD ["nginx", "-g", "daemon off;"]
ENTRYPOINT [ "/usr/sbin/nginx" ]

EXPOSE 80
EXPOSE 443</pre>
<p>
	这里基本与PHP的容器配置类似，执行playbook，共享网站目录，启动nginx服务并打开80，443端口。
</p>
<p>
	
</p>
<p>
	<span style="color:#337FE5;">ansible/nginx-container.yml</span>
</p>
<pre class="prettyprint lang-bsh">- name: Create Nginx container
  hosts: local
  vars:
    global_conf_path: /etc/nginx/nginx.conf
    server_conf_path: /etc/nginx/conf.d/default.conf
  tasks:
  - name: Install epel-release package
    yum: name=epel-release state=latest

  - name: Install required packages
    yum: name={{ item }} state=latest
    with_items:
      - net-tools
      - lsof
      - nmap
      - nginx

  - name: Copy nginx global conf
    copy: src=nginx.conf dest={{ global_conf_path }} mode=0644

  - name: Copy nginx server conf
    copy: src=default.conf dest={{ server_conf_path }} mode=0644</pre>
<p>
	这里安装nginx，并将配置文件复制到对应nginx目录.
</p>
<p>
	
</p>
<p>
	<span style="color:#337FE5;">ansible/defalut.conf</span>
</p>
<pre class="prettyprint"># The default server
#

upstream backend {
    server php:9000;
}

server {
    listen 80;
    server_name <a href="http://www.example.com" rel="nofollow">http://www.example.com</a>;
    root /data/app;
    index index.php index.html index.htm;

    location / {
          try_files $uri $uri/ =404;
    }

    location ~ \.php$ {
        fastcgi_pass backend;
        fastcgi_index index.php;
        include fastcgi.conf;
    }

}</pre>
<p>
	<span style="color:#337FE5;">ansible/nginx.conf</span>
</p>
<pre class="prettyprint"># For more information on configuration, see:
#   * Official English Documentation: <a href="http://nginx.org/en/docs/" rel="nofollow">http://nginx.org/en/docs/</a>
#   * Official Russian Documentation: <a href="http://nginx.org/ru/docs/" rel="nofollow">http://nginx.org/ru/docs/</a>

user nobody;
worker_processes 1;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
daemon off;

# Load dynamic modules. See /usr/share/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf;

events {
    worker_connections 768;
}

http {
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile            on;
    tcp_nopush          on;
    tcp_nodelay         on;
    keepalive_timeout   65;
    types_hash_max_size 2048;

    include             /etc/nginx/mime.types;
    default_type        application/octet-stream;

    # Load modular configuration files from the /etc/nginx/conf.d directory.
    # See <a href="http://nginx.org/en/docs/ngx_core_module.html#include" rel="nofollow">http://nginx.org/en/docs/ngx_core_module.html#include</a>
    # for more information.
    include /etc/nginx/conf.d/*.conf;

    server {
        listen       80 default_server;
        listen       [::]:80 default_server;
        server_name  _;
        root         /usr/share/nginx/html;

        # Load configuration files for the default server block.
        include /etc/nginx/default.d/*.conf;

        location / {
        }

        error_page 404 /404.html;
            location = /40x.html {
        }

        error_page 500 502 503 504 /50x.html;
            location = /50x.html {
        }
    }

# Settings for a TLS enabled server.
#
#    server {
#        listen       443 ssl http2 default_server;
#        listen       [::]:443 ssl http2 default_server;
#        server_name  _;
#        root         /usr/share/nginx/html;
#
#        ssl_certificate "/etc/pki/nginx/server.crt";
#        ssl_certificate_key "/etc/pki/nginx/private/server.key";
#        ssl_session_cache shared:SSL:1m;
#        ssl_session_timeout  10m;
#        ssl_ciphers HIGH:!aNULL:!MD5;
#        ssl_prefer_server_ciphers on;
#
#        # Load configuration files for the default server block.
#        include /etc/nginx/default.d/*.conf;
#
#        location / {
#        }
#
#        error_page 404 /404.html;
#            location = /40x.html {
#        }
#
#        error_page 500 502 503 504 /50x.html;
#            location = /50x.html {
#        }
#    }

}</pre>
<p><span style="color:#337FE5;">run.sh</span> </p>
<pre class="prettyprint lang-bsh">#/bin/bash

IMAGE="leon/nginx"
Container="nginx"
Link="php"
Volume="php"

docker build -t ${IMAGE} .

docker run -d -p 80:80 -p 443:443 --name ${Container} --link ${Link}:${Link} --volumes-from ${Volume} ${IMAGE}</pre>
<p>这里需要注意的是我们添加了一个--volumes-from参数用来调用PHP share出来的网站目录。</p>
<p>
	
</p>
<p>
	这里我们分别执行3个目录下的执行脚本(run.sh)后，效果如下:
</p>
<p>
	#&nbsp;docker ps
</p>
<pre class="prettyprint lang-bsh">CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                                      NAMES
7e6188415cb2        leon/php            "/usr/sbin/php-fpm -F"   2 hours ago         Up About an hour    0.0.0.0:9000-&gt;9000/tcp                     php
29ae9593fbfc        leon/mariadb        "./mariadb.sh"           2 hours ago         Up About an hour    0.0.0.0:3306-&gt;3306/tcp                     mariadb
d07bb4aea5c1        leon/nginx          "/usr/sbin/nginx"        3 days ago          Up 4 hours          0.0.0.0:80-&gt;80/tcp, 0.0.0.0:443-&gt;443/tcp   nginx</pre>
<p>
	
</p>
<p>
	#&nbsp;docker images
</p>
<pre class="prettyprint lang-bsh">REPOSITORY                     TAG                 IMAGE ID            CREATED             SIZE
leon/php                       latest              f243f43c99a2        3 hours ago         883 MB
leon/mariadb                   latest              7046c76b434a        3 hours ago         1.694 GB
leon/nginx                     latest              d588d0a73eee        7 days ago          737.6 MB
ansible/centos7-ansible        stable              5108f665e079        3 weeks ago         433.3 MB</pre>
<p>
	
</p>
<p>
	
</p>
<p>
	到这里我们就成功创建并启动了我们Wordpress所需要的三个基础服务。
</p>
<p>
	我们可以利用<strong>Docker start "容器名"</strong>或者<strong>Docker stop "容器名" </strong>去启动或者关闭这个包含具体服务的容器，可以作为我们在Docker服务器下重启服务的命令。
</p>
<p>
	如果需要进入容器进行调测，我们也可以使用<strong>Docker exec -it </strong><strong>"容器名" bash</strong>
</p>
<p>
	<strong><br />
</strong>
</p>
<p>
	测试结果
</p>
<p>
	我们给MAC主机添加一个host记录
</p>
<p>
	# cat /etc/hosts
</p>
<pre class="prettyprint lang-bsh">127.0.0.1 <a href="http://www.example.com" rel="nofollow">http://www.example.com</a></pre>
<p>
	
</p>
<p>
	
</p>
<p>
	然后使用PHP测试文件分别测试PHP是否部署成功以及PHP与MariaDB是否联通
</p>
<p>
	<a href="http://www.showerlee.com/wp-content/uploads/2016/12/test-db-conn.jpg"><img onerror="javascript:this.src='http://www.showerlee.com/wp-content/themes/BYMT/images/images_error.jpg'" src="http://www.showerlee.com/wp-content/uploads/2016/12/test-db-conn-1024x279.jpg" alt="test-db-conn" width="1024" height="279" class="alignnone size-large wp-image-1940" /></a> <a href="http://www.showerlee.com/wp-content/uploads/2016/12/phpinfo.jpg"><img onerror="javascript:this.src='http://www.showerlee.com/wp-content/themes/BYMT/images/images_error.jpg'" src="http://www.showerlee.com/wp-content/uploads/2016/12/phpinfo-1024x720.jpg" alt="phpinfo" width="1024" height="720" class="alignnone size-large wp-image-1941" /></a>
</p>
<p>
	
</p>
<p>
	
</p>
<p>
	最终我们访问www.example.com查看wordpress是否部署成功。
</p>
<p>
	<a href="http://www.showerlee.com/wp-content/uploads/2016/12/wp-install.jpg"><img onerror="javascript:this.src='http://www.showerlee.com/wp-content/themes/BYMT/images/images_error.jpg'" src="http://www.showerlee.com/wp-content/uploads/2016/12/wp-install-1024x797.jpg" alt="wp-install" width="1024" height="797" class="alignnone size-large wp-image-1942" /></a>
</p>
<p>
	
</p>
<p>
	<a href="http://www.showerlee.com/wp-content/uploads/2016/12/admin.jpg"><img onerror="javascript:this.src='http://www.showerlee.com/wp-content/themes/BYMT/images/images_error.jpg'" src="http://www.showerlee.com/wp-content/uploads/2016/12/admin-1024x567.jpg" alt="admin" width="1024" height="567" class="alignnone size-large wp-image-1957" /></a> <a href="http://www.showerlee.com/wp-content/uploads/2016/12/index.jpg"><img onerror="javascript:this.src='http://www.showerlee.com/wp-content/themes/BYMT/images/images_error.jpg'" src="http://www.showerlee.com/wp-content/uploads/2016/12/index-1024x553.jpg" alt="index" width="1024" height="553" class="alignnone size-large wp-image-1958" /></a>
</p>
<p>
	
</p>
<p>
	<span>至此使用Docker+Ansible部署Wordpress大功告成。。。&nbsp;</span></p>
<div>声明: 本文采用 <a rel="external" href="http://creativecommons.org/licenses/by-nc-sa/3.0/deed.zh" title="署名-非商业性使用-相同方式共享 3.0 Unported">CC BY-NC-SA 3.0</a> 协议进行授权</div><div>转载请注明来源：<a rel="external" title="DevOps技术分享" href="http://www.showerlee.com/archives/1938">DevOps技术分享</a></div><div>本文链接地址：<a rel="external" title="Mac+Docker+Ansible部署WordPress Application" href="http://www.showerlee.com/archives/1938">http://www.showerlee.com/archives/1938</a></div>]]></content:encoded>
			<wfw:commentRss>http://www.showerlee.com/archives/1938/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Dockerfile详解</title>
		<link>http://www.showerlee.com/archives/1837</link>
		<comments>http://www.showerlee.com/archives/1837#comments</comments>
		<pubDate>Thu, 31 Dec 2015 09:15:47 +0000</pubDate>
		<dc:creator>showerlee</dc:creator>
				<category><![CDATA[DevTools]]></category>
		<category><![CDATA[Docker]]></category>
		<category><![CDATA[Docerfile]]></category>

		<guid isPermaLink="false">http://www.showerlee.com/?p=1837</guid>
		<description><![CDATA[Docker可以通过获取Dockerfile编写的命令自动Build出一个新的镜像,里面的Docker内建命令 [&#8230;]]]></description>
				<content:encoded><![CDATA[<p><a href="http://www.showerlee.com/archives/tag/docker" title="查看Docker中的全部文章" class="tag_link">Docker</a>可以通过获取<a href="http://www.showerlee.com/archives/tag/docker" title="查看Docker中的全部文章" class="tag_link">Docker</a>file编写的命令自动Build出一个新的镜像,里面的<a href="http://www.showerlee.com/archives/tag/docker" title="查看Docker中的全部文章" class="tag_link">Docker</a>内建命令会帮助我们在已有的image下创建一个新的定制image.</p>
<p>
	这里我们先给大家介绍一些常用<a href="http://www.showerlee.com/archives/tag/docker" title="查看Docker中的全部文章" class="tag_link">Docker</a>file编写规范.
</p>
<p>
	<a href="http://www.showerlee.com/archives/tag/docker" title="查看Docker中的全部文章" class="tag_link">Docker</a>配置传送门:&nbsp;<a href="http://www.showerlee.com/archives/1758" rel="nofollow">http://www.showerlee.com/archives/1758</a>
</p>
<p>
	
</p>
<p>
	<span style="color:#337FE5;font-size:14px;">1.FROM&nbsp;</span>
</p>
<p>
	FROM &lt;image&gt;:&lt;tag&gt;
</p>
<p>FROM会使用当前本地或者远程<a href="http://www.showerlee.com/archives/tag/docker" title="查看Docker中的全部文章" class="tag_link">Docker</a>仓库的image, 这个要首先写到该脚本的第一行.</p>
<p>
	例:
</p>
<p>
	
</p>
<pre class="prettyprint lang-bsh">FROM centos67base/apache:apache_base</pre>
<p>
	
</p>
<p>
	这里代表我们使用本地的centos67base/apache镜像.
</p>
<p>
	查看本地缓存镜像可以使用
</p>
<p>
	# docker images
</p>
<p>
	
</p>
<p>
	<span style="color:#337FE5;font-size:14px;">2.MAINTAINER</span>
</p>
<p>
	MAINTAINER &lt;name&gt;
</p>
<p>
	这个会给生成的镜像创建一个作者名
</p>
<p></p>
<p>
	<span style="font-size:14px;color:#337FE5;">3.RUN</span>
</p>
<p>
	RUN &lt;command&gt; (命令行格式, 执行一段shell命令)
</p>
<p>
	RUN ["executable", "param1", "param2"] (列表格式, "executable"可以更改不同shell格式, 例如/bin/sh或/bin/bash, "param1"代表shell参数)
</p>
<p>
	这个可以理解为执行shell命令到image, 一般来说用来给镜像安装package, 或者更改系统配置等.
</p>
<p>
	例:
</p>
<pre class="prettyprint lang-bsh">RUN /bin/bash -c echo 123
RUN ["/bin/bash" "-c" "echo 123"]</pre>
<p>
	
</p>
<p><span style="color:#337FE5;font-size:14px;">4.CMD</span></p>
<p>
	CMD ["executable","param1","param2"] (同RUN)
</p>
<p>
	CMD ["param1","param2"] (使用系统默认shell)
</p>
<p>
	CMD command param1 param2 (命令行格式)
</p>
<p>这个CMD基本使用格式与RUN类似, 区别在于如果存在多个CMD行, 则只有最后一行生效, 这个我们常用执行默认的shell命令给该容器.</p>
<p>
	
</p>
<p>
	<span style="font-size:14px;color:#337FE5;">5.LABEL</span>
</p>
<p>
	LABEL &lt;key&gt;=&lt;value&gt; &lt;key&gt;=&lt;value&gt; &lt;key&gt;=&lt;value&gt; ...
</p>
<p>
	例:
</p>
<pre class="prettyprint lang-bsh">LABEL "com.example.vendor"="ACME Incorporated"
LABEL com.example.label-with-value="foo"
LABEL version="1.0"
LABEL description="This text illustrates \
that label-values can span multiple lines."</pre>
<p>
	这个可以理解为给image传送一个键值对.
</p>
<p>
	可以使用如下命令查看已Build好的image LABEL
</p>
<p>
	# docker inspect
</p>
<p></p>
<p>
	<span style="color:#337FE5;font-size:14px;">6.EXPOSE</span>
</p>
<p>
	EXPOSE &lt;port&gt; [&lt;port&gt;...]
</p>
<p>这个用来通知容器在某一具体端口进行监听, 但不会打开该端口, 如需打开要在创建容器容器的时候配合-P参数使用.</p>
<p>
	<span style="font-size:14px;color:#337FE5;">7.ENV</span>
</p>
<p>
	ENV &lt;key&gt; &lt;value&gt;
</p>
<p>
	ENV &lt;key&gt;=&lt;value&gt; ...
</p>
<p>
	例如:
</p>
<pre class="prettyprint lang-bsh">ENV myName="John Doe" myDog=Rex\ The\ Dog \
       myCat=fluffy</pre>
<p>
	相当于给镜像添加环境变量.
</p>
<p></p>
<p>
	<span style="font-size:14px;color:#337FE5;">8.ADD</span>
</p>
<p>
	ADD &lt;src&gt;... &lt;dest&gt;
</p>
<p>
	ADD ["&lt;src&gt;",... "&lt;dest&gt;"] (这种写法会避免路径名含有空格而报错)
</p>
<p>
	ADD命令会copy本地目录, 文件或远程URL到容器目的路径, &lt;src&gt;, &lt;dest&gt;支持通配符和绝对相对路径.
</p>
<p>
	例如:
</p>
<pre class="prettyprint lang-bsh">ADD hom* /mydir/        # adds all files starting with "hom"
ADD hom?.txt /mydir/    # ? is replaced with any single character, e.g., "home.txt"
ADD test relativeDir/   # adds "test" to `WORKDIR`/relativeDir/
ADD test /absoluteDir   # adds "test" to /absoluteDir</pre>
<p>
<span style="font-size:14px;color:#337FE5;">9.COPY</span></p>
<p>
	COPY &lt;src&gt;... &lt;dest&gt;
</p>
<p>
	COPY ["&lt;src&gt;",... "&lt;dest&gt;"] (这种写法会避免路径名含有空格而报错)
</p>
<p>
	本身用法和ADD类似, 唯独不能使用远程URL
</p>
<p></p>
<p>
	<span style="font-size:14px;color:#337FE5;">10.VOLUME</span>
</p>
<p>VOLUME ["/data"]<br />
VOLUME会给该image创建一个挂载点.</p>
<p>
	<span style="color:#337FE5;font-size:14px;">11.WORKDIR</span>
</p>
<p>
	WORKDIR /path/to/workdir
</p>
<p>顾名思义, 指定一个当前的工作目录.</p>
<p>
	<span style="color:#337FE5;font-size:14px;"><br />
</span>
</p>
<p>
	<span style="color:#337FE5;font-size:14px;">12.<a href="http://www.showerlee.com/archives/tag/docker" title="查看Docker中的全部文章" class="tag_link">Docker</a>file实例</span>
</p>
<pre class="prettyprint lang-bsh"># Nginx
#
# VERSION               0.0.1

FROM      ubuntu
MAINTAINER Victor Vieux &lt;victor@docker.com&gt;

LABEL Description="This image is used to start the foobar executable" Vendor="ACME Products" Version="1.0"
RUN apt-get update &amp;&amp; apt-get install -y inotify-tools nginx apache2 openssh-server


# Firefox over VNC
#
# VERSION               0.3</pre>
<pre class="prettyprint lang-bsh">FROM ubuntu

# Install vnc, xvfb in order to create a 'fake' display and firefox
RUN apt-get update &amp;&amp; apt-get install -y x11vnc xvfb firefox
RUN mkdir ~/.vnc
# Setup a password
RUN x11vnc -storepasswd 1234 ~/.vnc/passwd
# Autostart firefox (might not be the best way, but it does the trick)
RUN bash -c 'echo "firefox" &gt;&gt; /.bashrc'

EXPOSE 5900
CMD    ["x11vnc", "-forever", "-usepw", "-create"]
</pre>
<p>
	更多详细配置请参考:&nbsp;<a href="http://www.showerlee.com/archives/1758" rel="nofollow">http://www.showerlee.com/archives/1758</a> 第10项
</p>
<p></p>
<div>声明: 本文采用 <a rel="external" href="http://creativecommons.org/licenses/by-nc-sa/3.0/deed.zh" title="署名-非商业性使用-相同方式共享 3.0 Unported">CC BY-NC-SA 3.0</a> 协议进行授权</div><div>转载请注明来源：<a rel="external" title="DevOps技术分享" href="http://www.showerlee.com/archives/1837">DevOps技术分享</a></div><div>本文链接地址：<a rel="external" title="Dockerfile详解" href="http://www.showerlee.com/archives/1837">http://www.showerlee.com/archives/1837</a></div>]]></content:encoded>
			<wfw:commentRss>http://www.showerlee.com/archives/1837/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MAC+VirtualBox+Docker搭建私有CentOS Docker容器</title>
		<link>http://www.showerlee.com/archives/1758</link>
		<comments>http://www.showerlee.com/archives/1758#comments</comments>
		<pubDate>Tue, 15 Dec 2015 09:30:39 +0000</pubDate>
		<dc:creator>showerlee</dc:creator>
				<category><![CDATA[DevTools]]></category>
		<category><![CDATA[Docker]]></category>

		<guid isPermaLink="false">http://www.showerlee.com/?p=1758</guid>
		<description><![CDATA[Docker源意码头工人, 是一款更轻量级的虚拟化快速部署工具, 他的优点在于非常傻瓜的配置和管理, CPU/ [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>
	<span style="line-height:1.5;"><a href="http://www.showerlee.com/wp-content/uploads/2015/12/QQ20151215-0.png"><img onerror="javascript:this.src='http://www.showerlee.com/wp-content/themes/BYMT/images/images_error.jpg'" src="http://www.showerlee.com/wp-content/uploads/2015/12/QQ20151215-0.png" alt="QQ20151215-0" width="624" height="364" class="alignnone size-full wp-image-1766" /></a><br />
</span>
</p>
<p>
	<span style="line-height:1.5;"><a href="http://www.showerlee.com/archives/tag/docker" title="查看Docker中的全部文章" class="tag_link">Docker</a>源意码头工人, 是一款更轻量级的虚拟化快速部署工具, 他的优点在于非常傻瓜的配置和管理, CPU/内存的低消耗, 快速开/关机, 可以非常方便的运行和释放容器, 便捷的连接宿主机器和容器以及0成本的commit and export到其他任意环境, 绝对是一款优于vagrant等同类型工具的SA居家旅行必备利器.</span>
</p>
<p>
	<span style="line-height:1.5;"><span style="color:#E53333;">通俗来讲Docker其实就是将我们在虚拟机上定制的系统打包成一个私有Docker镜像, 然后通过将镜像传到本地, Docker本身会利用Vbox创建一个虚拟机实例(该虚拟机内核支持Docker)并与本地共享同一个目录结构, 最终利用docker内嵌命令使用我们的私有镜像创建若干子虚拟容器, 从而实现本地虚拟化部署.</span><br />
</span>
</p>
<p>
	<span style="line-height:1.5;"><span style="color:#E53333;"><span style="color:#E53333;">Windows与MAC平台内核因为本身与Docker不兼容, 所以我们需要本地安装VirtualBox+Docker, 利用VirtualBox创建一个可兼容Docker的虚拟机.</span></span></span>
</p>
<p>
	<span style="line-height:1.5;"><span style="color:#E53333;"><span style="color:#E53333;">Linux内核为3.0以上的发行版可直接安装Docker, 无需安装第三方虚拟机.</span></span></span>
</p>
<p>
	本文将详细介绍如何创建一个私有的Docker容器, 并部署到不同环境中, 使用Windows和Linux平台的同学也可以参考本文的配置.
</p>
<p>
	话说一开始我是拒绝的, 但经过2天的研究和部署, 我震精了, 这他喵的绝对是神一般的利器, 他的跨平台的一些功能(有待挖掘)绝对可以成为未来的运维部署发展趋势.
</p>
<p>
	还有不得不佩服老外的想象力, <span>这官网的</span>动物代表不同的系统环境, Docker代表码头工人的对不同系统环境的迁移整合,&nbsp;整得都成动物世界了, 不过还真别说, 这码头工人的效率还真不错, 动物园的动物们对这小哥的发货效率绝对满意, 必须五星好评.
</p>
<p>
	不说了, 我去啃老外的面包去了....&nbsp;</p>
<p>官方文档: <a href="https://docs.docker.com" rel="nofollow">https://docs.docker.com</a>
</p>
<p>
	<strong><br />
</strong>
</p>
<p>
	<span style="color:#337FE5;font-size:16px;"><strong>一.环境部署</strong></span>
</p>
<p>Local system: &nbsp;MAC OS X 10.10.5<br />
VirtualBox: &nbsp; &nbsp;VirtualBox-5.0.10<br />
docker: &nbsp; DockerToolbox-1.9.1b.pkg<br />
Docker sample system: CentOS6.7 x64 minimal (docker.example.com)</p>
<p>
	本机需安装Virtualbox和Docker, &nbsp;安装过程(略).
</p>
<p>
	<span style="color:#E53333;">TIP:本机为ubuntu或其他Linux发行版内核为3.0以上的朋友因为本地系统内嵌KVM, Docker可直接调用KVM, 所以</span><span style="color:#E53333;">无需安装Virtualbox作为Docker虚拟机.</span>
</p>
<p>
	
</p>
<p>
	<span style="color:#337FE5;font-size:16px;"><strong>二.Docker配置</strong></span>
</p>
<p>
	<span style="color:#337FE5;font-size:14px;">1.在Virtualbox新建虚拟机并安装CentOS 6.7 x64(略)</span>
</p>
<p>
	<span style="color:#337FE5;font-size:14px;">2.安装openssh-clients&nbsp;(VirtualBox虚拟机)</span>
</p>
<p>
	# yum install openssh-clients -y
</p>
<p>
	<span style="color:#337FE5;font-size:14px;">3.登陆CentOS虚拟机并安装EPEL YUM源&nbsp;(<span style="color:#337FE5;font-size:14px;line-height:21px;">VirtualBox</span>虚拟机)</span>
</p>
<p># rpm -Uvh <a href="http://download.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm" rel="nofollow">http://download.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm</a></p>
<p>
	<span style="color:#337FE5;font-size:14px;">4.配置yum&nbsp;(<span style="color:#337FE5;font-size:14px;line-height:21px;">VirtualBox</span>虚拟机)</span>
</p>
<p># cd /etc/yum.repos.d<br />
# vi CentOS-Base.repo<br />
找到[centosplus]源下,修改enabled=1<br />
# sed -i 's/$releasever/6/g' CentOS-Base.repo<br />
# sed -i 's/$basearch/x86_64/g' CentOS-Base.repo</p>
<p>
	<span style="color:#337FE5;font-size:14px;">5.安装Docker并开启Docker服务&nbsp;<span style="color:#337FE5;font-size:14px;line-height:21px;">(<span style="color:#337FE5;font-size:14px;line-height:21px;">VirtualBox</span>虚拟机)</span></span>
</p>
<p># yum install docker-io -y<br />
# service docker start</p>
<p>
	<span style="color:#337FE5;font-size:14px;">6.部署docker</span>
</p>
<p>
	<span style="color:#337FE5;">1).常用命令(本地)</span>
</p>
<p># docker images</p>
<pre class="prettyprint lang-bsh">REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE</pre>
<p># docker ps -a</p>
<pre class="prettyprint lang-bsh">CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES</pre>
<p>可以看到目前docker并未有可用的镜像.</p>
<p>
	<span style="color:#337FE5;">2).配置脚本目录 (<span style="color:#337FE5;line-height:21px;">VirtualBox</span>虚拟机)</span>
</p>
<p># cd /root</p>
<p>
	# mkdir scripts
</p>
<p># cd scripts</p>
<p>
	# vi createimg.sh
</p>
<p><span style="color:#E53333;">源自:<a href="https://github.com/docker/docker/blob/master/contrib/mkimage-yum.sh" rel="nofollow">https://github.com/docker/docker/blob/master/contrib/mkimage-yum.sh</a></span></p>
<pre class="prettyprint lang-bsh">#!/usr/bin/env bash
#
# Create a base CentOS Docker image.
#
# This script is useful on systems with yum installed (e.g., building
# a CentOS image on CentOS).  See contrib/mkimage-rinse.sh for a way
# to build CentOS images on other systems.

usage() {
    cat &lt;&lt;EOOPTS
$(basename $0) [OPTIONS] &lt;name&gt;
OPTIONS:
  -y &lt;yumconf&gt;  The path to the yum config to install packages from. The
                default is /etc/yum.conf for Centos/RHEL and /etc/dnf/dnf.conf for Fedora
EOOPTS
    exit 1
}

# option defaults
yum_config=/etc/yum.conf
if [ -f /etc/dnf/dnf.conf ] &amp;&amp; command -v dnf &amp;&gt; /dev/null; then
yum_config=/etc/dnf/dnf.conf
alias yum=dnf
fi 
while getopts ":y:h" opt; do
    case $opt in
        y)
            yum_config=$OPTARG
            ;;
        h)
            usage
            ;;
        \?)
            echo "Invalid option: -$OPTARG"
            usage
            ;;
    esac
done
shift $((OPTIND - 1))
name=$1

if [[ -z $name ]]; then
    usage
fi

target=$(mktemp -d --tmpdir $(basename $0).XXXXXX)

set -x

mkdir -m 755 "$target"/dev
mknod -m 600 "$target"/dev/console c 5 1
mknod -m 600 "$target"/dev/initctl p
mknod -m 666 "$target"/dev/full c 1 7
mknod -m 666 "$target"/dev/null c 1 3
mknod -m 666 "$target"/dev/ptmx c 5 2
mknod -m 666 "$target"/dev/random c 1 8
mknod -m 666 "$target"/dev/tty c 5 0
mknod -m 666 "$target"/dev/tty0 c 4 0
mknod -m 666 "$target"/dev/urandom c 1 9
mknod -m 666 "$target"/dev/zero c 1 5

# amazon linux yum will fail without vars set
if [ -d /etc/yum/vars ]; then
mkdir -p -m 755 "$target"/etc/yum
cp -a /etc/yum/vars "$target"/etc/yum/
fi

yum -c "$yum_config" --installroot="$target" --releasever=/ --setopt=tsflags=nodocs \
    --setopt=group_package_types=mandatory -y groupinstall Core
yum -c "$yum_config" --installroot="$target" -y clean all

cat &gt; "$target"/etc/sysconfig/network &lt;&lt;EOF
NETWORKING=yes
HOSTNAME=localhost.localdomain
EOF

# effectively: febootstrap-minimize --keep-zoneinfo --keep-rpmdb --keep-services "$target".
#  locales
rm -rf "$target"/usr/{{lib,share}/locale,{lib,lib64}/gconv,bin/localedef,sbin/build-locale-archive}
#  docs and man pages
rm -rf "$target"/usr/share/{man,doc,info,gnome/help}
#  cracklib
rm -rf "$target"/usr/share/cracklib
#  i18n
rm -rf "$target"/usr/share/i18n
#  yum cache
rm -rf "$target"/var/cache/yum
mkdir -p --mode=0755 "$target"/var/cache/yum
#  sln
rm -rf "$target"/sbin/sln
#  ldconfig
rm -rf "$target"/etc/ld.so.cache "$target"/var/cache/ldconfig
mkdir -p --mode=0755 "$target"/var/cache/ldconfig

version=
for file in "$target"/etc/{redhat,system}-release
do
    if [ -r "$file" ]; then
        version="$(sed 's/^[^0-9\]*\([0-9.]\+\).*$/\1/' "$file")"
        break
    fi
done

if [ -z "$version" ]; then
    echo &gt;&amp;2 "warning: cannot autodetect OS version, using '$name' as tag"
    version=$name
fi

tar --numeric-owner -c -C "$target" . | docker import - $name:$version

docker run -i -t $name:$version echo success

rm -rf "$target"</pre>
<p># chmod +x createimg.sh</p>
<p>
	<span style="color:#337FE5;">3).执行脚本(<span style="color:#337FE5;font-size:12px;line-height:21px;">VirtualBox</span>虚拟机)</span>
</p>
<p>
	该脚本将自动生成docker镜像,centos6.7base为镜像名,脚本执行log保存在/tmp下
</p>
<p># ./createimg.sh centos6.7base</p>
<p>
	<span style="color:#337FE5;">4).查看生成的docker镜像<span style="color:#337FE5;">(<span style="color:#337FE5;line-height:21px;">VirtualBox</span>虚拟机)</span></span>
</p>
<p># docker images</p>
<pre class="prettyprint lang-bsh">REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
centos6.7base       6.7                 8355bdcdcde0        5 minutes ago       166.3 MB</pre>
<p></p>
<p>
	<span style="color:#337FE5;">5).查看生成的docker容器<span style="color:#337FE5;">(<span style="color:#337FE5;line-height:21px;">VirtualBox</span>虚拟机)</span></span>
</p>
<p># docker ps -a</p>
<pre class="prettyprint lang-bsh">CONTAINER ID        IMAGE               COMMAND             CREATED              STATUS                          PORTS               NAMES
a7392bd18606        centos6.7base:6.7   "echo success"      About a minute ago   Exited (0) About a minute ago                       sleepy_swartz </pre>
<p>
	<span style="color:#337FE5;">6).删除容器<span style="color:#337FE5;"><span style="color:#337FE5;">(</span><span style="color:#337FE5;line-height:21px;">VirtualBox</span><span style="color:#337FE5;"></span><span style="color:#337FE5;">虚拟机)</span></span></span>
</p>
<p># docker rm a7392bd18606</p>
<p>
	<span style="color:#337FE5;">7).导出Docker缓存镜像到磁盘<span style="color:#337FE5;"><span style="color:#337FE5;">(</span><span style="color:#337FE5;line-height:21px;">VirtualBox</span><span style="color:#337FE5;"></span><span style="color:#337FE5;">虚拟机)</span></span></span>
</p>
<p># docker save 8355bdcdcde0 &gt; /tmp/centos67base.tar<br />
# ll /tmp</p>
<pre class="prettyprint lang-bsh">-rw-r--r--  1 root root 174095360 Dec 14 04:23 centos67base.tar
-rw-r--r--  1 root root     20284 Oct 16 03:21 vboxguest-Module.symvers
-rw-------. 1 root root         0 Oct 16 00:21 yum.log</pre>
<p>
	<span style="color:#337FE5;">8).拷贝该镜像到本地(本地)</span>
</p>
<p><span style="color:#E53333;">Tip: 因为笔者是MAC系统, 所以系统自带CLI scp命令, windows用户可以使用winscp进行ssh传输.</span></p>
<p>
	# cd ~/Work/Docker/centos67base
</p>
<p># scp <a href="mailto:root@docker.example.com">root@docker.example.com</a>:/tmp/centos67base.tar .</p>
<p>
	<span style="color:#337FE5;font-size:14px;">7.使用MAC下的docker加载该镜像</span>
</p>
<p>
	在MAC Application/Docker目录下运行Docker Quickstart Terminal, 会弹出Terminal并运行docker的相应初始化配置, 完成后会进入CLI界面.
</p>
<p>
	<span style="color:#E53333;">TIP: </span><span style="color:#E53333;">这里实际上是Docker调用了本地VirtualBox, 并在其创建了一个新的Docker虚拟机instance(可以通过打开VBOX GUI查看), 所以我们实际上已经进入了这个instance CLI界面, 但笔者惊奇的发现这里的目录结构和MAC本地是一致的, 可以得出来的结论是Docker和MAC共同share一个CLI. 所以大家可能会有错觉自己还在本地, 实际情况是我们已经登录到Docker母虚拟机, 随后我们会在这个母机上创建多个容器(子虚拟机).</span>
</p>
<p>
	Windows平台下该执行文件可在开始菜单获取
</p>
<p>
	<span style="color:#337FE5;">1).加载刚才制作的镜像<span style="color:#337FE5;">(Docker CLI)</span><span style="color:#337FE5;"></span></span>
</p>
<p># docker load &lt; centos67base.tar<br />
# docker images</p>
<pre class="prettyprint lang-bsh">REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
&lt;none&gt;              &lt;none&gt;              8355bdcdcde0        21 hours ago        166.3 MB</pre>
<p>
	<span style="color:#337FE5;">2).添加Repository和tag<span style="color:#337FE5;"><span style="color:#337FE5;"><span style="color:#337FE5;">(Docker CLI)</span></span></span><span style="color:#337FE5;"></span></span>
</p>
<p>默认这两项都为空,所以可以根据IMAGE ID去给这个image添加相关的标注<br />
# docker tag 8355bdcdcde0 centos67base:6.7<br />
# docker images</p>
<pre class="prettyprint lang-bsh">REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
centos67base        6.7                 8355bdcdcde0        21 hours ago        166.3 MB</pre>
<p>
	<span style="color:#337FE5;">3).创建docker容器并加载该镜像<span style="color:#337FE5;"><span style="color:#337FE5;"><span style="color:#337FE5;"><span style="color:#337FE5;">(Docker CLI)</span></span></span></span><span style="color:#337FE5;"></span></span>
</p>
<p>
	# docker run -i -t --privileged 8355bdcdcde0 /bin/bash
</p>
<p>
	<span style="color:#E53333;">Tip: -i和-t配合使用实际上是为了保持一个TTY标准输入处于一个LISTEN状态无论是否被连接, 简单来说就是创建一个CLI终端连接.</span>
</p>
<p>
	<span style="color:#E53333;">&nbsp; &nbsp; &nbsp; &nbsp;</span><span style="color:#E53333;">--privileged用来开启扩展权限给容器, 主要开启容器iptables等类似内核集成模块, 默认无此参数使用iptables会报错.</span>
</p>
<p>
	<span style="color:#E53333;">&nbsp; &nbsp; &nbsp; &nbsp;</span><span style="color:#E53333;">8355bdcdcde0为IMAGE ID, /bin/bash表示使用bash shell格式进入终端.</span>
</p>
<p>
	<span style="color:#000000;"><span style="color:#000000;">已成功登录子虚拟容器</span></span>
</p>
<p># uname -a &nbsp; &nbsp;</p>
<pre class="prettyprint lang-bsh">Linux 33e93edb56e3 4.1.13-boot2docker #1 SMP Fri Nov 20 19:05:50 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux</pre>
<p># cat /etc/system-release</p>
<pre class="prettyprint lang-bsh">CentOS release 6.7 (Final)</pre>
<p>可以看到已经登陆到子虚拟容器, 至此我们就成功制作并加载了我们私有的docker镜像.</p>
<p>
	<span style="color:#337FE5;">4).关闭<span style="color:#337FE5;">子虚拟容器</span></span>
</p>
<p># exit<br />
# docker ps -a</p>
<pre class="prettyprint lang-bsh">CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                     PORTS               NAMES
33e93edb56e3        8355bdcdcde0        "/bin/bash"         16 minutes ago      Exited (0) 8 seconds ago                       awesome_joliot</pre>
<p>这里可以看到这个容器在16分钟前生成, 现已经关闭了8秒钟, 简单来说这里去退出Docker容器可以理解为虚拟机的保存状态(挂起), 在我们创建这个容器后的所有的change都不会丢失, 除非你删除这个容器, 但之前开启的服务socket会丢失, 所以重新打开这个容器需重启该服务.</p>
<p>
	<span style="color:#337FE5;">5).重新开启并连接该容器<span style="color:#337FE5;"><span style="color:#337FE5;">(Docker CLI)</span></span><span style="color:#337FE5;"></span></span>
</p>
<p>
	# docker start 33e93edb56e3
</p>
<p>
	# docker attach 33e93edb56e3
</p>
<p><span style="color:#E53333;">Tip: 这里执行attach后不会立即进入容器命令行,需要再回车才能显示.</span></p>
<p>
	<span style="color:#337FE5;">6).断开该容器<span style="color:#337FE5;"><span style="color:#337FE5;">(Docker CLI)</span></span><span style="color:#337FE5;"></span></span>
</p>
<p>
	这里可以在CLI下利用快捷键ctrl+P, 然后Ctrl+Q去快速切回本地环境.
</p>
<p># docker ps -a</p>
<pre class="prettyprint lang-bsh">CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
33e93edb56e3        8355bdcdcde0        "/bin/bash"         33 minutes ago      Up 7 minutes                            awesome_joliot</pre>
<p>
	这里可以看到容器并没有退出, 其状态显示为已运行7分钟.
</p>
<p>
	
</p>
<p>
	<span style="color:#337FE5;">8).重命名该容器<span style="color:#337FE5;">(Docker CLI)</span></span>
</p>
<p>
	#&nbsp;docker rename awesome_joliot&nbsp;centos6.7_base
</p>
<pre class="prettyprint lang-bsh">CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
33e93edb56e3        8355bdcdcde0        "/bin/bash"         35 minutes ago      Up 9 minutes                            centos6.7_base</pre>
<p>
	<span style="color:#337FE5;">9).重新连接该容器<span style="color:#337FE5;"><span style="color:#337FE5;">(Docker CLI)</span></span><span style="color:#337FE5;"></span></span>
</p>
<p>
	# docker attach 33e93edb56e3
</p>
<p>
	这里也可以直接使用刚才修改后的容器名登陆&nbsp;
</p>
<p>
	#&nbsp;docker attach centos6.7_base
</p>
<p><span style="color:#E53333;">所以实际上整个Docker的运行步骤:</span><br />
<span style="color:#E53333;"> 加载tar包到docker缓存镜像 =&gt; 利用该镜像创建容器 =&gt; 启动容器 =&gt; 连接容器</span></p>
<p>
	<span style="color:#337FE5;">8).删除并重新创建容器<span style="color:#337FE5;"><span style="color:#337FE5;">(Docker CLI)</span></span><span style="color:#337FE5;"></span></span>
</p>
<p>
	# docker rm 33e93edb56e3
</p>
<p>
	# docker run -i -t --privileged 8355bdcdcde0 /bin/bash
</p>
<p>
	# exit
</p>
<p>$ docker ps -a</p>
<pre class="prettyprint lang-bsh">CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                     PORTS               NAMES
861dd99563ef        8355bdcdcde0        "/bin/bash"         18 seconds ago      Exited (0) 2 seconds ago                       gloomy_lovelace</pre>
<p>我们可以看到容器ID变成861dd99563ef, 之前的容器和容器的所有change已经彻底删除.</p>
<p>到这里我们介绍了Docker的使用, 基本上公司sa会将一份基本的Docker系统镜像分发给每位开发人员, 开发人员会利用这个统一的系统环境去coding, 如果在开发过程中遇到了一个BUG或者问题无法修复, 如何将当前的状态备份并分发给其他同事去处理? 这里就可以利用Dock commit去保存我们的系统状态到镜像中, 利用之前的命令export and transfer该镜像给相应Programmer进行进一步的处理, 当然我们也可以利用该功能去保存不同开发产品的版本状态.</p>
<p>
	
</p>
<p>
	<span style="color:#337FE5;font-size:14px;">8.Commit Docker镜像<span style="color:#337FE5;"><span style="color:#337FE5;">(Docker CLI)</span></span><span style="color:#337FE5;"></span></span>
</p>
<p>
	我们可以安装一个apache并commit镜像来模拟上述情况.
</p>
<p># docker start 861dd99563ef</p>
<pre class="prettyprint lang-bsh">e8b478f41b5c</pre>
<p>
	# docker attach 861dd99563ef
</p>
<p>
	# exit
</p>
<p># docker commit 861dd99563ef centos67base/apache:apache_base</p>
<pre class="prettyprint lang-bsh">d9aef85ea282439634c36b3e8d51356396bb116c6ea51f11f8b128bf1fdb89a6</pre>
<p># docker images</p>
<pre class="prettyprint lang-bsh">REPOSITORY            TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
centos67base/apache   apache_base         d9aef85ea282        7 seconds ago       233.6 MB
centos67base          6.7                 8355bdcdcde0        23 hours ago        166.3 MB</pre>
<p>我们可以看到我们生成了一个基于centos67base的apache版本镜像</p>
<p>
	<span style="color:#337FE5;font-size:14px;">9.导出该新版本镜像<span style="color:#337FE5;"><span style="color:#337FE5;">(Docker CLI)</span></span><span style="color:#337FE5;"></span></span>
</p>
<p>
	# docker save centos67base/apache &gt; centos67_apache.tar
</p>
<p># ll</p>
<pre class="prettyprint lang-bsh">-rw-r--r-- 1 XXX staff 242053632 Dec 15 16:34 centos67_apache.tar
-rw-r--r-- 1 XXX staff 174095360 Dec 15 13:26 centos67base.tar</pre>
<p>
	<span><span style="font-size:12px;line-height:21px;color:#E53333;">TIP: 由于Docker虚拟机与本地MAC share一个CLI, 这里相当于这个镜像已经保存在本地.</span></span>
</p>
<p>
	<span><span style="font-size:12px;line-height:21px;color:#E53333;"><span style="color:#337FE5;"><br />
</span></span></span>
</p>
<p>
	<span><span style="font-size:12px;line-height:21px;color:#E53333;"><span style="color:#337FE5;"><span style="font-size:14px;">10.通过</span><span style="font-size:14px;">Dockerfile</span><span style="font-size:14px;"> Build虚拟镜像</span><span style="color:#337FE5;font-size:14px;line-height:21px;">(Docker CLI)</span><span style="font-size:14px;"></span></span></span></span>
</p>
<p>
	<span><span style="font-size:12px;line-height:21px;color:#000000;"><span style="color:#337FE5;">1).这里我们通过Docker脚本在原有</span><span style="color:#E53333;"><span style="color:#E53333;">centos67base/apache</span><span style="color:#337FE5;">镜像基础上</span></span><span style="color:#337FE5;">安装vim, 实现一个简单的自动化部署.</span></span></span>
</p>
<p>
	<span><span style="font-size:12px;line-height:21px;color:#E53333;"><span style="color:#337FE5;"><span style="color:#000000;"># cd ~/Work/Docker/Build</span></span></span></span>
</p>
<p>
	<span><span style="font-size:12px;line-height:21px;color:#E53333;"><span style="color:#337FE5;"><span style="color:#000000;"># </span><span style="color:#000000;">vi Dockerfile</span><span style="color:#000000;"></span></span></span></span>
</p>
<p>
	<span><span style="font-size:12px;line-height:21px;color:#E53333;"><span style="color:#337FE5;"><span style="color:#000000;"> </span></span></span></span>
</p>
<pre class="prettyprint lang-bsh">FROM centos67base/apache:apache_base
RUN yum install vim -y</pre>
<p>
	<span style="color:#E53333;">TIP: 这里centos67base/apache:apache_base对应<strong>REPOSITORY</strong></span><span style="color:#E53333;"><strong>:TAG</strong></span>
</p>
<p>
	<span style="color:#337FE5;">2).开始Build</span>
</p>
<p>
	<span style="color:#000000;">#&nbsp;docker build -t centos67base/apache/vim .</span>
</p>
<p>
	<span><span style="font-size:12px;line-height:21px;color:#E53333;"><span style="color:#337FE5;"><span style="color:#000000;"> </span></span></span></span>
</p>
<pre class="prettyprint lang-bsh">Sending build context to Docker daemon 416.2 MB
Step 1 : FROM centos67base/apache:apache_base
 ---&gt; d9aef85ea282
Step 2 : RUN yum install vim -y
 ---&gt; Running in 721c0cd73025
Loaded plugins: fastestmirror
Setting up Install Process
Determining fastest mirrors
 * base: mirrors.yun-idc.com
 * extras: mirrors.yun-idc.com
 * updates: mirrors.yun-idc.com
Resolving Dependencies
--&gt; Running transaction check
---&gt; Package vim-enhanced.x86_64 2:7.4.629-5.el6 will be installed
--&gt; Processing Dependency: vim-common = 2:7.4.629-5.el6 for package: 2:vim-enhanced-7.4.629-5.el6.x86_64
--&gt; Processing Dependency: which for package: 2:vim-enhanced-7.4.629-5.el6.x86_64
--&gt; Processing Dependency: perl(:MODULE_COMPAT_5.10.1) for package: 2:vim-enhanced-7.4.629-5.el6.x86_64
--&gt; Processing Dependency: libperl.so()(64bit) for package: 2:vim-enhanced-7.4.629-5.el6.x86_64
--&gt; Processing Dependency: libgpm.so.2()(64bit) for package: 2:vim-enhanced-7.4.629-5.el6.x86_64
--&gt; Running transaction check
---&gt; Package gpm-libs.x86_64 0:1.20.6-12.el6 will be installed
---&gt; Package perl.x86_64 4:5.10.1-141.el6_7.1 will be installed
--&gt; Processing Dependency: perl(version) for package: 4:perl-5.10.1-141.el6_7.1.x86_64
--&gt; Processing Dependency: perl(Pod::Simple) for package: 4:perl-5.10.1-141.el6_7.1.x86_64
--&gt; Processing Dependency: perl(Module::Pluggable) for package: 4:perl-5.10.1-141.el6_7.1.x86_64
---&gt; Package perl-libs.x86_64 4:5.10.1-141.el6_7.1 will be installed
---&gt; Package vim-common.x86_64 2:7.4.629-5.el6 will be installed
--&gt; Processing Dependency: vim-filesystem for package: 2:vim-common-7.4.629-5.el6.x86_64
---&gt; Package which.x86_64 0:2.19-6.el6 will be installed
--&gt; Running transaction check
---&gt; Package perl-Module-Pluggable.x86_64 1:3.90-141.el6_7.1 will be installed
---&gt; Package perl-Pod-Simple.x86_64 1:3.13-141.el6_7.1 will be installed
--&gt; Processing Dependency: perl(Pod::Escapes) &gt;= 1.04 for package: 1:perl-Pod-Simple-3.13-141.el6_7.1.x86_64
---&gt; Package perl-version.x86_64 3:0.77-141.el6_7.1 will be installed
---&gt; Package vim-filesystem.x86_64 2:7.4.629-5.el6 will be installed
--&gt; Running transaction check
---&gt; Package perl-Pod-Escapes.x86_64 1:1.04-141.el6_7.1 will be installed
--&gt; Finished Dependency Resolution

Dependencies Resolved

================================================================================
 Package                  Arch      Version                    Repository  Size
================================================================================
Installing:
 vim-enhanced             x86_64    2:7.4.629-5.el6            base       1.0 M
Installing for dependencies:
 gpm-libs                 x86_64    1.20.6-12.el6              base        28 k
 perl                     x86_64    4:5.10.1-141.el6_7.1       updates     10 M
 perl-Module-Pluggable    x86_64    1:3.90-141.el6_7.1         updates     40 k
 perl-Pod-Escapes         x86_64    1:1.04-141.el6_7.1         updates     33 k
 perl-Pod-Simple          x86_64    1:3.13-141.el6_7.1         updates    213 k
 perl-libs                x86_64    4:5.10.1-141.el6_7.1       updates    579 k
 perl-version             x86_64    3:0.77-141.el6_7.1         updates     52 k
 vim-common               x86_64    2:7.4.629-5.el6            base       6.7 M
 vim-filesystem           x86_64    2:7.4.629-5.el6            base        15 k
 which                    x86_64    2.19-6.el6                 base        38 k

Transaction Summary
================================================================================
Install      11 Package(s)

Total download size: 19 M
Installed size: 59 M
Downloading Packages:
--------------------------------------------------------------------------------
Total                                           7.0 MB/s |  19 MB     00:02     
Running rpm_check_debug
Running Transaction Test
Transaction Test Succeeded
Running Transaction
  Installing : 1:perl-Pod-Escapes-1.04-141.el6_7.1.x86_64                  1/11 
  Installing : 1:perl-Module-Pluggable-3.90-141.el6_7.1.x86_64             2/11 
  Installing : 3:perl-version-0.77-141.el6_7.1.x86_64                      3/11 
  Installing : 4:perl-libs-5.10.1-141.el6_7.1.x86_64                       4/11 
  Installing : 1:perl-Pod-Simple-3.13-141.el6_7.1.x86_64                   5/11 
  Installing : 4:perl-5.10.1-141.el6_7.1.x86_64                            6/11 
  Installing : 2:vim-filesystem-7.4.629-5.el6.x86_64                       7/11 
  Installing : 2:vim-common-7.4.629-5.el6.x86_64                           8/11 
  Installing : which-2.19-6.el6.x86_64                                     9/11 
  Installing : gpm-libs-1.20.6-12.el6.x86_64                              10/11 
  Installing : 2:vim-enhanced-7.4.629-5.el6.x86_64                        11/11 
  Verifying  : 1:perl-Pod-Simple-3.13-141.el6_7.1.x86_64                   1/11 
  Verifying  : 1:perl-Pod-Escapes-1.04-141.el6_7.1.x86_64                  2/11 
  Verifying  : gpm-libs-1.20.6-12.el6.x86_64                               3/11 
  Verifying  : which-2.19-6.el6.x86_64                                     4/11 
  Verifying  : 2:vim-enhanced-7.4.629-5.el6.x86_64                         5/11 
  Verifying  : 2:vim-filesystem-7.4.629-5.el6.x86_64                       6/11 
  Verifying  : 1:perl-Module-Pluggable-3.90-141.el6_7.1.x86_64             7/11 
  Verifying  : 2:vim-common-7.4.629-5.el6.x86_64                           8/11 
  Verifying  : 3:perl-version-0.77-141.el6_7.1.x86_64                      9/11 
  Verifying  : 4:perl-libs-5.10.1-141.el6_7.1.x86_64                      10/11 
  Verifying  : 4:perl-5.10.1-141.el6_7.1.x86_64                           11/11 

Installed:
  vim-enhanced.x86_64 2:7.4.629-5.el6                                           

Dependency Installed:
  gpm-libs.x86_64 0:1.20.6-12.el6                                               
  perl.x86_64 4:5.10.1-141.el6_7.1                                              
  perl-Module-Pluggable.x86_64 1:3.90-141.el6_7.1                               
  perl-Pod-Escapes.x86_64 1:1.04-141.el6_7.1                                    
  perl-Pod-Simple.x86_64 1:3.13-141.el6_7.1                                     
  perl-libs.x86_64 4:5.10.1-141.el6_7.1                                         
  perl-version.x86_64 3:0.77-141.el6_7.1                                        
  vim-common.x86_64 2:7.4.629-5.el6                                             
  vim-filesystem.x86_64 2:7.4.629-5.el6                                         
  which.x86_64 0:2.19-6.el6                                                     

Complete!
 ---&gt; dfd4d0e4442c
Removing intermediate container 721c0cd73025
Successfully built dfd4d0e4442c</pre>
<p># docker images</p>
<p>
	<span><span style="font-size:12px;line-height:21px;color:#E53333;"><span style="color:#337FE5;"><span style="color:#000000;"> </span></span></span></span>
</p>
<pre class="prettyprint lang-bsh">REPOSITORY                TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
centos67base/apache/vim   latest              dfd4d0e4442c        10 seconds ago      327 MB
centos67base/apache       apache_base         d9aef85ea282        2 weeks ago         233.6 MB</pre>
<p>这里我们就在之前镜像的基础上Build出一个新的image, 有特殊需求的同学可以在此脚本的基础上编写更加详细的部署步骤.</p>
<p>
	<span style="line-height:21px;">更多配置可以参考官方文档: <a href="https://docs.docker.com/engine/reference/builder/" rel="nofollow">https://docs.docker.com/engine/reference/builder/</a></span><span style="line-height:21px;"></span><span style="line-height:21px;">&nbsp;</span>
</p>
<p>
	
</p>
<p>
	<span style="line-height:21px;"><span style="color:#337FE5;font-size:14px;line-height:21px;">11. 本地与容器间传输文件</span></span>
</p>
<p>
	我们可以通过docker内建命令docker cp对已创建好的容器来进行文件传输.
</p>
<p>
	# docker ps -a
</p>
<pre class="prettyprint lang-bsh">CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
3d9136b53a7f        8355bdcdcde0        "/bin/bash"         6 minutes ago       Up 6 minutes                            centos67base</pre>
<p>
	
</p>
<p>
	<span style="line-height:1.5;"># ls</span>
</p>
<p>
	
</p>
<pre class="prettyprint lang-bsh">Dockerfile </pre>
<p><span style="line-height:1.5;"></span><span style="line-height:1.5;">#&nbsp;</span><span style="line-height:1.5;">docker cp Dockerfile centos67base:/Dockerfile</span><span style="line-height:1.5;"></span> </p>
<p>
	
</p>
<p>
	#&nbsp;docker attach centos67base
</p>
<p>
	# ls
</p>
<pre class="prettyprint lang-bsh">Dockerfile  boot  etc   lib    media  opt   root  selinux  sys  usr
bin         dev   home  lib64  mnt    proc  sbin  srv      tmp  var</pre>
<p>
	
</p>
<p>
	<span style="color:#337FE5;font-size:14px;">12. 访问容器端口</span>
</p>
<p>
	如果我们需要在本地MAC访问容器的具体服务, 我们可以通过DOCKER的NAT Forwarding来实现访问该容器端口服务.
</p>
<p>
	这里我们可以利用之前安装的apache实现MAC本地访问容器的apache web服务.
</p>
<p>
	<span style="color:#337FE5;">1). 创建apache容器, 并打开其80 NAT Forwarding&nbsp;<span style="color:#337FE5;">(Docker CLI)</span></span>
</p>
<p>
	# docker run -i -t --privileged -p 80:80 d9aef85ea282 /bin/bash
</p>
<p>
	<span style="color:#E53333;">Tip: 80:80 前者为母虚拟机端口, 后者为子虚拟容器端口</span><span style="color:#E53333;"></span>
</p>
<p>
	<span style="color:#337FE5;">2). 登陆进容器, 开启apache服务并登出(子虚拟容器)</span>
</p>
<p>
	# service httpd start
</p>
<p>
	# echo "This is a test web page" &gt; /var/www/html/index.html
</p>
<p>
	Ctrl+P, 然后Ctrl+Q登出
</p>
<p>
	<span style="color:#337FE5;">3).访问该服务<span style="color:#337FE5;">(Docker CLI)</span><span style="color:#337FE5;"></span></span>
</p>
<p>
	查看Docker母虚拟机IP信息
</p>
<p>
	#&nbsp;docker-machine ls
</p>
<pre class="prettyprint lang-bsh">NAME      ACTIVE   DRIVER       STATE     URL                         SWARM   ERRORS
default   *        virtualbox   Running   tcp://192.168.99.101:2376</pre>
<p>查看子容器NAT配置</p>
<p>
	#&nbsp;docker ps -a
</p>
<p>
	# docker port&nbsp;cce502d8a21a
</p>
<pre class="prettyprint lang-bsh">80/tcp -&gt; 0.0.0.0:80</pre>
<p>
	这里可以看到NAT已配置成功
</p>
<p>
	<span>成功访问web服务</span>
</p>
<p>
	# curl&nbsp;<a href="http://192.168.99.101/" rel="nofollow">http://192.168.99.101/</a>
</p>
<p>
	<span id="__kindeditor_bookmark_start_81__"> </span>
</p>
<pre class="prettyprint lang-bsh">This is a test web page!!!!</pre>
<p>
	<span style="color:#E53333;">TIP: 这里由于我们实际上是在VirtualBox下的一个Docker instance虚拟机下, 所以访问的IP为</span><span style="color:#E53333;">192.168.99.101, 而不是本地127.0.0.1.</span>
</p>
<p>
	<span style="color:#E53333;">这里再次给同学们强调虽然我们的目录结构感觉是在本地, 但实际上我们处在Docker虚拟机下, 只是这个虚拟机嵌入到本地目录中.</span>
</p>
<p>
	
</p>
<p>
	<span style="line-height:1.5;"></span>
</p>
<p>
	至此我们大致将SA的Docker原理, 制作过程和配置使用详细讲解给大家, 其中借鉴了很多老外的部署经验, 希望有英语基础的同学可以去国外的技术网站去获取相关的知识. 随后我会陆续更新Docker自动化部署等文档.
</p>
<p>
Hope you enjoy…</p>
<div>声明: 本文采用 <a rel="external" href="http://creativecommons.org/licenses/by-nc-sa/3.0/deed.zh" title="署名-非商业性使用-相同方式共享 3.0 Unported">CC BY-NC-SA 3.0</a> 协议进行授权</div><div>转载请注明来源：<a rel="external" title="DevOps技术分享" href="http://www.showerlee.com/archives/1758">DevOps技术分享</a></div><div>本文链接地址：<a rel="external" title="MAC+VirtualBox+Docker搭建私有CentOS Docker容器" href="http://www.showerlee.com/archives/1758">http://www.showerlee.com/archives/1758</a></div>]]></content:encoded>
			<wfw:commentRss>http://www.showerlee.com/archives/1758/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
