使用docker运行nginx

方法一、通过 Dockerfile构建

创建Dockerfile
首先,创建目录nginx,用于存放后面的相关东西。

runoob@runoob:~$ mkdir -p ~/nginx/www ~/nginx/logs ~/nginx/conf

www目录将映射为nginx容器配置的虚拟目录
logs目录将映射为nginx容器的日志目录
conf目录里的配置文件将映射为nginx容器的配置文件
进入创建的nginx目录,创建Dockerfile

FROM debian:jessie

MAINTAINER NGINX Docker Maintainers "[email protected]"

ENV NGINX_VERSION 1.10.1-1~jessie

RUN apt-key adv --keyserver hkp://pgp.mit.edu:80 --recv-keys 573BFD6B3D8FBC641079A6ABABF5BD827BD9BF62 
        && echo "deb http://nginx.org/packages/debian/ jessie nginx" >> /etc/apt/sources.list 
        && apt-get update 
        && apt-get install --no-install-recommends --no-install-suggests -y 
                                                ca-certificates 
                                                nginx=${NGINX_VERSION} 
                                                nginx-module-xslt 
                                                nginx-module-geoip 
                                                nginx-module-image-filter 
                                                nginx-module-perl 
                                                nginx-module-njs 
                                                gettext-base 
        && rm -rf /var/lib/apt/lists/*

# forward request and error logs to docker log collector
RUN ln -sf /dev/stdout /var/log/nginx/access.log 
        && ln -sf /dev/stderr /var/log/nginx/error.log

EXPOSE 80 443

CMD ["nginx", "-g", "daemon off;"]

通过Dockerfile创建一个镜像,替换成你自己的名字

docker build -t nginx .

创建完成后,我们可以在本地的镜像列表里查找到刚刚创建的镜像

runoob@runoob:~/nginx$ docker images nginx
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
nginx               latest              555bbd91e13c        3 days ago          182.8 MB

方法二、docker pull nginx

查找Docker Hub上的nginx镜像

runoob@runoob:~/nginx$ docker search nginx
NAME                      DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
nginx                     Official build of Nginx.                        3260      [OK]       
jwilder/nginx-proxy       Automated Nginx reverse proxy for docker c...   674                  [OK]
richarvey/nginx-php-fpm   Container running Nginx + PHP-FPM capable ...   207                  [OK]
million12/nginx-php       Nginx + PHP-FPM 5.5, 5.6, 7.0 (NG), CentOS...   67                   [OK]
maxexcloo/nginx-php       Docker framework container with Nginx and ...   57                   [OK]
webdevops/php-nginx       Nginx with PHP-FPM                              39                   [OK]
h3nrik/nginx-ldap         NGINX web server with LDAP/AD, SSL and pro...   27                   [OK]
bitnami/nginx             Bitnami nginx Docker Image                      19                   [OK]
maxexcloo/nginx           Docker framework container with Nginx inst...   7                    [OK]
...

这里我们拉取官方的镜像

runoob@runoob:~/nginx$ docker pull nginx

等待下载完成后,我们就可以在本地镜像列表里查到REPOSITORY为nginx的镜像。
使用nginx镜像
运行容器

runoob@runoob:~/nginx$ docker run -p 80:80 --name mynginx -v $PWD/www:/www -v $PWD/conf/nginx.conf:/etc/nginx/nginx.conf -v $PWD/logs:/wwwlogs  -d nginx  
45c89fab0bf9ad643bc7ab571f3ccd65379b844498f54a7c8a4e7ca1dc3a2c1e
runoob@runoob:~/nginx$

命令说明:
-p 80:80:将容器的80端口映射到主机的80端口
–name mynginx:将容器命名为mynginx
-v $PWD/www:/www:将主机中当前目录下的www挂载到容器的/www
-v $PWD/conf/nginx.conf:/etc/nginx/nginx.conf:将主机中当前目录下的nginx.conf挂载到容器的/etc/nginx/nginx.conf
-v $PWD/logs:/wwwlogs:将主机中当前目录下的logs挂载到容器的/wwwlogs
查看容器启动情况

runoob@runoob:~/nginx$ docker ps
CONTAINER ID        IMAGE        COMMAND                      PORTS                         NAMES
45c89fab0bf9        nginx        "nginx -g 'daemon off"  ...  0.0.0.0:80->80/tcp, 443/tcp   mynginx
f2fa96138d71        tomcat       "catalina.sh run"       ...  0.0.0.0:81->8080/tcp          tomcat

通过浏览器访问
虚拟化技术

ubuntu 16.04安装docker-ce v17.03

本文介绍在ubuntu 16.04 LTS安装最新版本的docker-ce,docker v17.03。目前docker分为docker-ce(社区版本),docker-ee(企业版本)。这里介绍docker-ce的安装。

先决条件

OS要求

要安装docker,需要如下64位ubuntu版本的系统
– Yakkety 16.10
– Xenial 16.04 (LTS)
– Trusty 14.04 (LTS)

卸载旧版本

旧的docker版本称为docker或docker-engine,如果安装了这些版本,先卸载它们:

$ sudo apt-get remove docker docker-engine

/var/lib/docker目录存储着镜像,容器,数据卷和网络,这些都会保留。

安装docker

配置仓库

1.配置apt可以使用https安装软件包

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

2.添加docker官方GPG key:

$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -

验证key批纹为9DC8 5822 9FC7 DD38 854A E2D8 8D81 803C 0EBF CD88.

$ sudo apt-key fingerprint 0EBFCD88

pub   4096R/0EBFCD88 2017-02-22
      Key fingerprint = 9DC8 5822 9FC7 DD38 854A  E2D8 8D81 803C 0EBF CD88
uid                  Docker Release (CE deb) <[email protected]>
sub   4096R/F273FCD8 2017-02-22

3.使用如下命令配置stable仓库。

$ sudo add-apt-repository 
   "deb [arch=amd64] https://download.docker.com/linux/ubuntu 
   $(lsb_release -cs) 
   stable"

安装docker

1.更新apt软件包索引

$ sudo apt-get update

2.安装最新版本的docker,或者到下一步安装指定版本的docker

sudo apt-get install docker-ce

3.在生产系统中,应该安装一个指定的docker版本,而不是最新的。执行如下命令列出可用的版本。

$ apt-cache madison docker-ce

docker-ce | 17.03.0~ce-0~ubuntu-xenial | https://download.docker.com/linux/ubuntu xenial/stable amd64 Packages

执行如下命令安装指定的版本:

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

CentOS 7安装Docker

先决条件

OS要求

需要64位的CentOS 7系统

卸载旧版本

Docker的旧版本称为docker或docker-engine。如果已经安装有,先卸载它及它的依赖

$ sudo yum remove docker 
                  docker-common 
                  container-selinux 
                  docker-selinux 
                  docker-engine

目前Docker CE(社区版本)称为docker-ce,Docker EE(企业版本)称为docker-ee。这里我们安装社区版本。

安装docker

配置仓库

1.安装yum-utils,提供了yum-config-manager工具:

$ sudo yum install -y yum-utils

2.使用如下命令配置一个稳定的仓库

$ sudo yum-config-manager 
    --add-repo 
    https://download.docker.com/linux/centos/docker-ce.repo

开始安装

1.更新yum软件包索引

$ sudo yum makecache fast

2.安装最新版本的docker

sudo yum install docker-ce

3.在生产系统,你应该安装一个指定版本的docker。列出所有可用版本

$ yum list docker-ce.x86_64  --showduplicates |sort -r

然后安装指定版本

sudo yum install docker-ce-<VERSION>

4.启动docker

$ sudo systemctl start docker

5.通过运行hello-world镜像来检测docker是否安装成功

$ sudo docker run hello-world

Docker部署WordPress LNMP(Nginx PHP MySQL)环境实践

Docker基于LXC实现了把软件封装到一个完整的文件系统,可以在docker容器中运行所需的一切代码,运行环境,系统工具和系统库。由于docker使用独立于主机的文件系统,可以确保软件在不同的主机环境中仍然保持运行环境不变。docker与主机共用一个操作系统内核,使用docker容器具有轻量级的特点,能占用更少的内存快速启动容器。

下面我们学习使用docker来部署目前非常流行的博客系统wordpress的运行环境nginx php mysql(作者wordpress博客devops.webres.wang正是运行在docker容器中)。那么docker部署wordpress的运行环境与我们传统上直接在主机配置环境有什么区别?我们从开发和运维人员角度来说明。运维使用docker制作好wordpress容器,分发给开发人员,开发人员随即只需一个命令就可以部署好完全一样的运行环境,从此只需要关注代码本身,而不再需要把时间浪费在配置环境上。而同时,docker容器确保了开发环境与生产环境的一致性,极大减少由于开发环境与生产环境不一致出现的各种问题。而由于docker容器可以快速部署的特点,运维人员可以很轻松的对服务进行伸缩和扩展。

那么如何使用docker部署wordpress的运行环境?大概步骤是分别编写nginx php mysql的Dockerfile文件,从这些Dockerfile文件中生成各自的镜像,然后使用docker-compose工具来统一管理nginx php mysql。为了能只使用docker-compose.yml一个文件就能快速部署wordpress环境,我们把Dockerfile及环境的相关配置保存到阿里云的Kelude(git代码托管code.aliyun.com),然后使用阿里云的Docker镜像仓库(cr.console.aliyun.com)从Kelude拉取Dockerfile自动构建镜像。国外此类服务有hub.docker.com和github.com,使用阿里云的是因为可以免费设置私有git仓库和私有镜像,因为我们可能需要保存一些不便公开的私密信息(如网站证书,密码)。当然你也可以不使用这类服务,直接把镜像保存到本地环境中。下面开始一步步介绍。

准备工作

使用阿里云Kelude

到https://code.aliyun.com/创建一个项目,如Dockerfile。之后我们把wordpress环境的所有相关Dockerfile及配置文件放置到centosbz目录。

使用阿里云镜像仓库

阿里云docker镜像仓库地址为https://cr.console.aliyun.com,用来存放docker镜像,可以在本地push镜像上去,也可以从Kelude拉取Dockerfile自动构建镜像。我们先登录,然后新建一个namespace,如centos-bz,之后所有的nginx,php,mysql镜像将存放在这个namespace下。

安装docker-compose

需要在运行docker容器的主机上安装docker-compose,可以参照官方文档手动安装,也可以使用ezhttp的一键安装工具(推荐)安装。如:

wget webres.wang/ezhttp.zip
unzip ezhttp.zip
cd ezhttp-master
./start.sh

之后会弹出一个菜单,输入2选择Some Useful Tools,然后输入18选择安装docker和compose。

编写Dockerfile

clone以上在阿里云Kelude创建的Dockerfile镜像到本地,在此项目中创建webres.wang,然后在webres.wang目录分别创建mysql,nginx,php目录,用于存放它们各自Dockerfile及配置文件。
这里我们还约定以下目录:

  • /home/docker/nginx/logs/webres.wang:存放devops.webres.wang网站的日志
  • /home/docker/nginx/www/webres.wang: 存放devops.webres.wang网站的文件
  • /home/docker/php: 存放php-fpm的日志
  • /home/docker/mysql:mysql data目录
  • nginx Dockerfile

    在nginx目录创建Dockerfile文件,写入如下内容:

    # 从debian:jessie镜像基础上安装nginx
    FROM debian:jessie
    
    # 声明此Dockerfile维护者的邮箱,有什么问题可以发到此邮件寻问
    LABEL maintainer "[email protected]"
    
    # 定义软件版本及编译工具变量
    ENV NGINX_VERSION 1.10.3
    ENV OPENSSL_VERSION 1.0.2h
    ENV ZLIB_VERSION 1.2.11
    ENV PCRE_VERSION 8.40
    ENV CONCAT_VERSION 1.2.2
    ENV BUILD_TOOLS wget gcc make g++
    ENV SRC_DIR /opt/nginx
    
    # 切换到工作目录
    WORKDIR ${SRC_DIR}
    
    # 开始编译nginx,我们这里使用编译安装nginx而不是使用官方提供的nginx镜像是因为这里使用到了第三方的concat模块,只能编译了。
    # 把所有的安装命令都写在一个RUN指令中是因为这样可以减小镜像层数,缩减镜像大小。推荐使用反斜杠和&&把所有的安装命令放置到一行中。
    RUN apt-get update 
        && apt-get -y --no-install-recommends install ca-certificates ${BUILD_TOOLS} 
        && wget http://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz  
        && wget https://www.openssl.org/source/openssl-${OPENSSL_VERSION}.tar.gz  
        && wget http://www.zlib.net/zlib-${ZLIB_VERSION}.tar.gz  
        && wget https://ftp.pcre.org/pub/pcre/pcre-${PCRE_VERSION}.tar.gz  
        && wget https://github.com/alibaba/nginx-http-concat/archive/${CONCAT_VERSION}.tar.gz -O nginx-http-concat-${CONCAT_VERSION}.tar.gz  
        && tar xf nginx-${NGINX_VERSION}.tar.gz  
        && tar xf openssl-${OPENSSL_VERSION}.tar.gz  
        && tar xf zlib-${ZLIB_VERSION}.tar.gz  
        && tar xf pcre-${PCRE_VERSION}.tar.gz  
        && tar xf nginx-http-concat-${CONCAT_VERSION}.tar.gz  
        && cd nginx-${NGINX_VERSION}  
        && ./configure --prefix=/usr/local/nginx --with-pcre=../pcre-${PCRE_VERSION} 
                    --with-zlib=../zlib-${ZLIB_VERSION} 
                    --with-http_ssl_module 
                    --with-openssl=../openssl-${OPENSSL_VERSION} 
                    --add-module=../nginx-http-concat-${CONCAT_VERSION}  
        && make -j$(nproc) 
        && make install 
        && rm -rf ${SRC_DIR} 
        && apt-get purge -y --auto-remove ${BUILD_TOOLS} 
        && rm -rf /var/lib/apt/lists/* 
    
    # 把构建上下文目录conf,即Dockerfile/webres.wang/nginx/conf目录下的文件复制到容器的/usr/local/nginx/conf目录。
    COPY conf/ /usr/local/nginx/conf/
    
    # 定义启动容器时运行的命令
    ENTRYPOINT ["/usr/local/nginx/sbin/nginx"]
    
    EXPOSE 80 443
    

    对于conf目录下的nginx配置文件,需要把日志,网站目录更改为以下约定的目录位置。

    php-fpm Dockerfile

    创建Dockerfile/webres.wang/php-fpm目录,在此目录下创建Dockerfile文件,内容如下:

    FROM debian:jessie
    LABEL maintainer "[email protected]"
    
    # 定义软件版本,编译工具,依赖等变量
    ENV PHP_VERSION 5.6.30
    ENV BUILD_TOOLS m4 
                   autoconf 
                   autoconf2.13 
                   openssl 
                   wget 
                   gcc 
                   make
    
    ENV BUILD_DEPS libcurl4-gnutls-dev 
                   libxml2-dev 
                   zlib1g-dev 
                   libpcre3-dev 
                   libjpeg-dev 
                   libpng12-dev 
                   libfreetype6-dev 
                   libmhash-dev 
                   libmcrypt-dev 
                   libssl-dev 
                   libtool
    
    ENV PHP_LOCATION /usr/local/php
    ENV BUILD_ARG   --prefix=${PHP_LOCATION} 
                    --with-config-file-path=${PHP_LOCATION}/etc 
                    --enable-fpm 
                    --enable-bcmath 
                    --with-pdo_sqlite 
                    --with-gettext 
                    --with-iconv 
                    --enable-ftp 
                    --with-sqlite3 
                    --enable-mbstring 
                    --enable-sockets 
                    --enable-zip 
                    --enable-soap 
                    --with-openssl 
                    --with-zlib 
                    --with-curl 
                    --with-gd 
                    --with-jpeg-dir 
                    --with-png-dir 
                    --with-freetype-dir 
                    --with-mcrypt 
                    --with-mhash 
                    --with-mysql=mysqlnd 
                    --with-mysqli=mysqlnd 
                    --with-pdo-mysql=mysqlnd 
                    --without-pear 
                    --with-libdir=lib64 
                    --enable-opcache 
                    --disable-cgi
    
    ENV SRC_DIR /opt/php
    
    WORKDIR ${SRC_DIR}
    
    # 开始编译安装php
    RUN apt-get update 
        && apt-get -y --no-install-recommends install ${BUILD_DEPS} ${BUILD_TOOLS} 
        && wget http://php.net/distributions/php-${PHP_VERSION}.tar.gz 
        && tar xf php-${PHP_VERSION}.tar.gz 
        && cd php-${PHP_VERSION} 
        && ln -s /usr/lib/x86_64-linux-gnu/libssl.so /usr/lib/libssl.so 
        && ln -s /usr/lib /usr/lib64 
        && ./configure ${BUILD_ARG} 
        && make -j$(nproc) 
        && make install 
        && cp php.ini-production ${PHP_LOCATION}/etc/php.ini 
        && cp ${PHP_LOCATION}/etc/php-fpm.conf.default ${PHP_LOCATION}/etc/php-fpm.conf 
        && rm -rf ${SRC_DIR} 
        && apt-get purge -y --auto-remove ${BUILD_TOOLS} 
        && rm -rf /var/lib/apt/lists/* 
    
    
    WORKDIR ${PHP_LOCATION}/etc/
    
    # 配置php-fpm,即使用sed工具编辑php-fpm.conf和php.ini文件,这里的php-fpm相关配置命令不与上面的编译命令合在一起来减小层数是因为
    # 配置文件可能会改动比较多,这样分开当配置文件更改时可以直接使用缓存跳过编译步骤,加快构建速度。
    RUN set_php_variable(){ 
            local key=$1; 
            local value=$2; 
            if grep -q -E "^$keys*=" php.ini;then 
                sed -i -r "s#^$keys*=.*#$key=$value#" php.ini; 
            else 
                sed -i -r "s#;s*$keys*=.*#$key=$value#" php.ini; 
            fi; 
            if ! grep -q -E "^$keys*=" php.ini;then 
                echo "$key=$value" >> php.ini; 
            fi; 
        } 
        && BASE_DIR=/home/docker/php 
        && set_php_variable disable_functions "dl,eval,assert,exec,popen,system,passthru,shell_exec,escapeshellarg,escapeshellcmd,proc_close,proc_open" 
        && set_php_variable expose_php Off 
        && set_php_variable error_log ${BASE_DIR}/php_errors.log 
        && set_php_variable request_order  "CGP" 
        && set_php_variable cgi.fix_pathinfo 0 
        && set_php_variable short_open_tag on 
        && set_php_variable date.timezone Asia/Chongqing 
        && sed -i 's/^user =.*/user = www-data/' php-fpm.conf 
        && sed -i 's/^group =.*/group = www-data/' php-fpm.conf 
        && sed -i "s#;slowlog = log/$pool.log.slow#slowlog = ${BASE_DIR}/$pool.log.slow#" php-fpm.conf 
        && sed -i 's/;request_slowlog_timeout = 0/request_slowlog_timeout = 5/' php-fpm.conf 
        && sed -i 's/^pm.max_children.*/pm.max_children =20/' php-fpm.conf 
        && sed -i 's/^pm.start_servers.*/pm.start_servers =5/' php-fpm.conf 
        && sed -i 's/^pm.min_spare_servers.*/pm.min_spare_servers =3/' php-fpm.conf 
        && sed -i 's/^pm.max_spare_servers.*/pm.max_spare_servers =8/' php-fpm.conf 
        && sed -i '/[global]/adaemonize =no' php-fpm.conf 
        && sed -i 's/^listen.*/listen =0.0.0.0:9000/' php-fpm.conf 
        && echo "[opcache]n 
                zend_extension=opcache.son 
                opcache.memory_consumption=128n 
                opcache.interned_strings_buffer=8n 
                opcache.max_accelerated_files=4000n 
                opcache.revalidate_freq=60n 
                opcache.fast_shutdown=1 n" >> php.ini
    
    ENTRYPOINT ["/usr/local/php/sbin/php-fpm"]
    
    EXPOSE 9000    
    

    mysql Dockerfile

    创建Dockerfile/webres.wang/mysql/Dockerfile文件,内容如下:

    FROM mysql:5.6
    LABEL maintainer "[email protected]"
    COPY my.cnf /etc/mysql/my.cnf
    

    这个Dockerfile非常简单,直接使用了官方的mysql镜像,唯一区别是我们使用自己定义的my.cnf配置文件。
    对于my.cnf配置文件,需要把日志,data目录指向/home/docker/mysql,一个my.cnf示例文件如下:

    # Generated by EZHTTP at 2016-02-03 01:05:29
    
    [mysql]
    
    # CLIENT #
    port                           = 3306
    socket                         = /home/docker/mysql/mysql.sock
    
    [mysqld]
    
    # GENERAL #
    port                           = 3306
    user                           = mysql
    default-storage-engine         = InnoDB
    socket                         = /home/docker/mysql/mysql.sock
    pid-file                       = /home/docker/mysql/mysql.pid
    skip-name-resolve
    
    # MyISAM #
    key-buffer-size                = 32M
    
    # INNODB #
    #innodb-flush-method            = O_DIRECT
    innodb-log-files-in-group      = 2
    innodb-log-file-size           = 64M
    innodb-flush-log-at-trx-commit = 2
    innodb-file-per-table          = 1
    innodb-buffer-pool-size        = 1G
    
    # CACHES AND LIMITS #
    tmp-table-size                 = 32M
    max-heap-table-size            = 32M
    query-cache-type               = 0
    query-cache-size               = 0
    max-connections                = 300
    thread-cache-size              = 50
    open-files-limit               = 1024
    table-definition-cache         = 100
    table-open-cache               = 400
    
    
    # SAFETY #
    max-allowed-packet             = 16M
    max-connect-errors             = 1000000
    
    # DATA STORAGE #
    datadir                        = /home/docker/mysql
    
    # LOGGING #
    log-error                      = /home/docker/mysql/mysql-error.log
    log-queries-not-using-indexes  = 1
    slow-query-log                 = 1
    slow-query-log-file            = /home/docker/mysql/mysql-slow.log
    
    # BINARY LOGGING #
    log-bin = /home/docker/mysql/mysql-bin
    server-id = 1
    expire-logs-days = 14
    sync-binlog = 1
    

    构建镜像

    把上一步创建的文件推送到阿里云的Kelude。然后我们登录阿里云的docker镜像仓库cr.console.aliyun.com。这里以设置自动构建nginx镜像为例,php和mysql镜像构建设置类似。
    1.点击左侧“镜像列表”,在右侧点击仓库镜像,如图:
    虚拟化技术
    2.在仓库镜像创建对话框中,说明如下:
    地域:选择离部署docker主机最近的位置,国内的话选择华东1或华东2。
    Namespace和仓库名称:这里选择centos-bz,nginx。
    设置代码源:我们这里选择阿里云code。
    构建设置:勾选代码变更时自动构建镜像,海外机器构建(因为国内主机apt-get安装软件时较慢),Dockerfile路径填/webres.wang/nginx
    完成后点击创建仓库按钮。
    如图:
    虚拟化技术
    3.回到镜像列表,找到nginx镜像,点击管理。
    4.左侧点击“构建”,右侧点击“立即构建”开始首次构建,之后我们更改Dockerfile及配置文件到Kelude之后就会自动构建了。
    5.查看日志,查看构建进程。
    然后继续完成php,mysql的镜像构建设置。

    启动环境

    为了方便统一管理nginx,php,mysql的启动,我们使用docker-compose工具。我们只需要编写一个docker-compose.yml文件,然后使用docker-compose工具就可以快速启动docker容器了。之后把docker-compose.yml传输到任意一台支持docker环境的主机中就可以快速配置wordpress的运行环境。

    docker-compose.yml

    把docker-compose.yml文件放置在/home/docker目录下。

    version: '3'
    # 定义三个服务nginx,php,mysql
    services:
        nginx:
            # 依赖php服务,意味着在启动nginx之前先启动php
            depends_on:
                - php
            # nginx镜像的路径
            image: registry.cn-hangzhou.aliyuncs.com/centos-bz/nginx
            # 容器的/home/docker/nginx目录挂载主机中的/home/docker/nginx目录,
            # 这样使nginx容器把网站文件和目录存放到主机目录中,持久化和方便管理
            volumes:
                - /home/docker/nginx:/home/docker/nginx
            # nginx意外退出时自动重启
            restart: always
    
            # 映射80和443端口
            ports:
                - "80:80"
                - "443:443"
    
            # 容器名称
            container_name: nginx    
        php:
            depends_on:
                - mysql
            image: registry.cn-hangzhou.aliyuncs.com/centos-bz/php-fpm
            restart: always
            volumes:
                - /home/docker/nginx/www:/home/docker/nginx/www
                - /home/docker/php:/home/docker/php
            container_name: php   
    
        mysql:
            image: registry.cn-hangzhou.aliyuncs.com/centos-bz/mysql
            volumes:
                - /home/docker/mysql:/home/docker/mysql
            restart: always
            # 设置MYSQL_ROOT_PASSWORD环境变量,这里是设置mysql的root密码。这里为root。
            environment:
                MYSQL_ROOT_PASSWORD: root
            container_name: mysql
    

    启动环境

    在/home/docker目录执行:

    docker-compose up
    

    查看nginx,php,mysql是否正常启动,如果正常,ctrl-c停止,再执行:

    docker-compose up -d
    

    这里compose命令就在后台启动了。
    执行docker ps查看容器运行状态。

    连接问题

    容器之间可以通过容器名称来连接,如nginx配置文件中连接php的代码fastcgi_pass php:9000,网站数据库配置文件使用mysql:3306。

    日常运维

    迁移

    比如A主机迁移到B主机。只需要三步。

  • 1.打包A主机的/home/docker目录,传输到B主机相同位置
  • 2.配置B主机docker环境
  • 3.在B主机的/home/docker目录下执行docker-compose up -d
  • 导出导入数据库

    把centos.sql.gz数据库文件导入到centos数据库:

    gunzip < centos.sql.gz | docker exec -i mysql mysql -uroot -proot centos
    

    把centos数据库导出到centos.sql.gz

    docker exec -i mysql mysqldump -uroot -proot centos | gzip > centos.sql.gz
    

    备份

    推荐使用ezhttp一键备份设置:

    wget webres.wang/ezhttp.zip
    unzip ezhttp.zip
    cd ezhttp-master
    ./start.sh
    

    之后会弹出一个菜单,输入2选择Some Useful Tools,然后输入14选择备份设置。需要注意的是在设置mysql使用mysqldump备份时,在提示输入mysql bin directory时,输入docker exec /usr/bin/。

    docker和compose一键快速安装脚本

    本文介绍快速安装docker和compose的方法。与手动安装相比,一键安装省去了手工输入命令的繁琐步骤且不容易出错。由于国内网络环境原因,连接docker官方服务器异常的慢,这体现为在国内安装docker-engine和拉取镜像非常慢,甚至无法安装和拉取。此脚本通过更换repository和registry mirror解决了此问题。

    脚本特性

    对于docker-engine的安装,脚本特性如下:

  • 支持centos7,ubuntu,debian系统的安装
  • 支持安装特定版本的docker
  • 根据网络环境测试结果自动选取较快的repository,如国内使用mirrors.ustc.edu.cn,国外使用dockerproject.org
  • 通过测试网络自动为国内设置hub-mirror.c.163.com registry mirror
  • 对于compose的安装,脚本特性如下:

  • 支持所有Linux系统的安装
  • 支持安装特定版本的compose
  • 由于compose托管在amazonaws,国内几乎无法访问,自动设置一个代理下载
  • 使用方法

    1. wget webres.wang/ezhttp.zip
    2. unzip ezhttp.zip
    3. cd ezhttp-master
    4. ./start.sh

    之后会弹出一个菜单,输入2选择Some Useful Tools.
    然后输入17选择安装docker,输入18选择安装compose。

    docker compose文件参考(4) – 变量替换

    配置项可以包含环境变量。compose使用docker-compose运行所在的shell环境的变量值。例如,假设shell包含环境变量EXTERNAL_PORT=8000且配置中引用了此变量:

    1. web:
    2.   build: .
    3.   ports:
    4.     – "${EXTERNAL_PORT}:5000"

    当使用此配置插docker-compose run命令时,compose在shell中查找EXTERNAL_PORT环境变量并使用其值替换此配置文件中对应的占位符。在这个示例中,在创建web容器之前,compose解析端口映射为8000:5000。

    如果环境变量没有设置,compose使用空字符替换。在上面的示例中,如果EXTERNAL_PORT没有设置,端口映射的值为:5000(是一个无效的端口映射,创建容器时会导致错误)。

    可以使用.env文件为环境变量设置默认的值。在shell环境中设置的值会覆盖在.env文件设置的值。

    1. $ unset EXTERNAL_PORT
    2. $ echo "EXTERNAL_PORT=6000" > .env
    3. $ docker-compose up          # EXTERNAL_PORT will be 6000
    4. $ export EXTERNAL_PORT=7000
    5. $ docker-compose up          # EXTERNAL_PORT will be 7000

    $VARIABLE和${VARIABLE}两种写法都支持。如果使用的是2.1文件格式,还可以在一行中设置默认的值:

  • ${VARIABLE:-default}:当VARIABLE没有设置或为空值时使用default值。
  • ${VARIABLE-default} :仅当VARIABLE没有设置时使用default值。
  • 其它的shell风格的扩展功能,如${VARIABLE/foo/bar}不支持。

    可以使用双美元符号来转义美元符号,即阻止compose解析为值。

    1. web:
    2.   build: .
    3.   command: "$$VAR_NOT_INTERPOLATED_BY_COMPOSE"

    docker compose文件参考(3) – 网络配置

    driver

    指定用于这个网络的驱动。

    默认使用的驱动取决于docker engine的配置,但大多数情况中,单台主机中使用的是bridge,在集群中使用的是overlay。

    1. driver: overlay

    driver_opts

    指定一列键值对选项传递给这个数据卷的驱动。这些选项依赖于驱动。此参数可选。

    1. driver_opts:
    2.     foo: "bar"
    3.     baz: 1

    enable_ipv6

    在这个网络启用IPv6网络支持。从version 2.1文件格式可用。

    ipam

    指定自定义IPAM配置。这个是带几个属性的对象,每个属性都是可选的:

  • driver: 自定义IPAM驱动,而不是default。
  • config: 0个或多个配置块,可以是以下键:
    subnet:表示一个网段的CIDR格式的子网
    ip_range:从指定范围分配容器IP
    gateway:主子网的IPv4或IPv6网关
    aux_addresses:网络驱动程序使用的辅助IPv4或IPv6地址,作为从主机名到IP的映射
  • 一个完整的示例:

    1. ipam:
    2.   driver: default
    3.   config:
    4.     – subnet: 172.28.0.0/16
    5.       ip_range: 172.28.5.0/24
    6.       gateway: 172.28.5.254
    7.       aux_addresses:
    8.         host1: 172.28.1.5
    9.         host2: 172.28.1.6
    10.         host3: 172.28.1.7

    docker compose文件参考(2) – 数据卷配置

    driver

    指定这个数据卷使用的数据卷驱动。默认为local。如果驱动不可用,docker engine将会返回一个错误。

    1. driver: foobar

    driver_opts

    指定一列键值对选项传递给这个数据卷的驱动。这些选项依赖于驱动。此参数可选。

    1. driver_opts:
    2.    foo: "bar"
    3.    baz: 1

    external

    如果设置为true,表示这个数据卷已经在compose外部创建好了。docker-compose up将不会尝试创建它。

    external不能与其它的数据卷配置关键词(driver, driver_opts)一起使用。

    在下面的示例中,compose不会尝试创建名为[projectname]_data的数据卷,而是仅仅查找一个称为data存在的数据卷并挂载它到db服务的容器。

    1. version: ‘2’
    2.  
    3. services:
    4.   db:
    5.     image: postgres
    6.     volumes:
    7.       – data:/var/lib/postgresql/data
    8.  
    9. volumes:
    10.   data:
    11.     external: true

    也可以指定在compose文件内引用的数据卷名称:

    1. volumes:
    2.   data:
    3.     external:
    4.       name: actual-name-of-volume

    docker compose文件参考(1) – 服务配置

    build

    这个配置选项应用在构建镜像时。

    build可以指定包含构建上下文路径的字符串,或者是context指定一个路径和可选的dockerfile和args。

    1. build: ./dir
    2.  
    3. build:
    4.   context: ./dir
    5.   dockerfile: Dockerfile-alternate
    6.   args:
    7.     buildno: 1

    如果指定了image和build,那么compose以image中指定的名称命名构建的镜像,如:

    1. build: ./dir
    2. image: webapp:tag

    compose将由./dir构建的镜像命名为webapp,tag为tag。

    注意:在version 1文件格式中,build有两点不同的地方:
    1.只允许build: .一种格式,不允许对象格式。
    2.不允许build与image一起使用。

    context

    context可用于verion 2文件格式或以上版本,version 1中只用build。

    指定一个包含Dockerfile的目录路径,或git存储库url。

    当指定了一个相对路径,就解析为相对compose文件所在的目录。这个目录也是发送到docker daemon的构建上下文。

    1. build:
    2.   context: ./dir

    dockerfile

    替代的Dockerfile

    compose使用另一个dockerfile文件构建镜像。必须指定一个context构建路径。

    注意:在verions 1文件格式中,dockerfile有两点不同:
    1.它出现在build的同级,而不是作为它的子选项:

    1. build: .
    2. dockerfile: Dockerfile-alternate

    2.不允许dockerfile与image一起使用。

    args

    此选项只支持version 2文件格式和之上版本。

    增加build参数,这些参数是只在构建期间访问的环境变量。

    首先,在Dockerfile中指定参数:

    1. ARG buildno
    2. ARG password
    3.  
    4. RUN echo "Build number: $buildno"
    5. RUN script-requiring-password.sh "$password"

    然后在build下面指定参数。可以传递映射或列表:

    1. build:
    2.   context: .
    3.   args:
    4.     buildno: 1
    5.     password: secret
    6.  
    7. build:
    8.   context: .
    9.   args:
    10.     – buildno=1
    11.     – password=secret

    compose文件中可以只指定参数名不设置值,在这种情况下参数的值就是compose运行所在shell的环境变量值。

    1. args:
    2.   – buildno
    3.   – password

    注意:YAML布尔值(true,false,yes,no,on,off)必须用引号引起来,以便解析器将其解释为字符串。

    command

    覆盖默认的命令。

    1. command: bundle exec thin -p 3000

    命令也可以是一个列表,与dockerfile中的列表类似:

    1. command: [bundle, exec, thin, -p, 3000]

    container_name

    指定一个自定义的容器名称,而不是一个生成的默认名称。

    1. container_name: my-web-container

    因为docker容器名称必须是唯一的,所以如果指定了一个自定义的名称,不能扩展一个服务超过1个容器。

    depends_on

    指定服务之间的依赖关系,有两种效果:

  • docker-compose up将以依赖顺序启动服务。在下面的示例中,db和redis在web之前启动。
  • docker-compose up SERVICE将自动包括SERVICE的依赖。在下面的示例中,docker-compose up web也会创建和启动db和redis。
  • 简单的示例:

    1. version: ‘2’
    2. services:
    3.   web:
    4.     build: .
    5.     depends_on:
    6.       – db
    7.       – redis
    8.   redis:
    9.     image: redis
    10.   db:
    11.     image: postgres

    注意:depends_on不会等到db和redis状态为“ready”才启动web – 它只等到它们已经开始启动。如果需要等到一个服务变为ready,查看Controlling startup order

    dns

    自定义DNS服务器。可以是单个值或列表。

    1. dns: 8.8.8.8
    2. dns:
    3.   – 8.8.8.8
    4.   – 9.9.9.9

    dns_search

    自定义search域名。可以是单个值或列表。

    1. dns_search: example.com
    2. dns_search:
    3.   – dc1.example.com
    4.   – dc2.example.com

    tmpfs

    需要version 2文件格式或以上版本。

    在容器内部挂载一个临时文件系统。可以是单个值或列表。

    tmpfs: /run
    tmpfs:
    – /run
    – /tmp

    entrypoint

    覆盖默认的entrypoint。

    1. entrypoint: /code/entrypoint.sh

    entrypoint也可以是一个列表:

    1. entrypoint:
    2.     – php
    3.     – -d
    4.     – zend_extension=/usr/local/lib/php/extensions/no-debug-non-zts-20100525/xdebug.so
    5.     – -d
    6.     – memory_limit=-1
    7.     – vendor/bin/phpunit

    注意:设置entrypoint将会覆盖默认使用ENTRYPOINT Dockerfile指令设置服务镜像的entrypoint,也会清除这个镜像的任何默认命令 – 意味着如果Dockerfile中指定的任何CMD指定将会忽略。

    env_file

    从一个文件添加环境变量。可以是单个值或列表。

    如果使用docker-compose -f FILE指定了一个compose文件,那么在env_file的路径就是相对于那个文件所在的目录。

    在environment关键词指定的环境变量将会覆盖env_file设置的值。

    1. env_file: .env
    2.  
    3. env_file:
    4.   – ./common.env
    5.   – ./apps/web.env
    6.   – /opt/secrets.env

    env文件中每行的格式为VAR=VAL。以#开头的行将忽略,也包括空行。

    1. # Set Rails/Rack environment
    2. RACK_ENV=development

    注意:如果服务指定了一个build选项,定义在env文件中的变量在构建期间不可用。使用build的子选项来定义在构建期间使用的环境变量。

    VAL的值按原样使用,不再不修改。 例如,如果值由引号括起来(通常是shell变量的情况),引号将包含在传递给Compose的值中。

    environment

    添加环境变量。可以使用数组或字典。任何的布尔值,true,false,yes,no需要用引号括起来,以确保YML解析器把它们转换为True或False。

    1. environment:
    2.   RACK_ENV: development
    3.   SHOW: ‘true’
    4.   SESSION_SECRET:
    5.  
    6. environment:
    7.   – RACK_ENV=development
    8.   – SHOW=true
    9.   – SESSION_SECRET

    expose

    暴露只在链接服务之间可用的端口。只能指定内部使用的端口。

    1. expose:
    2.  – "3000"
    3.  – "8000"

    extends

    在当前文件或另一个文件扩展另一个服务,可选地覆盖配置。

    extends可以与service相关的配置项一起使用。extends的值必须是一个字典,其中service是必须的以及一个可选的file选项。

    1. extends:
    2.   file: common.yml
    3.   service: webapp

    service指定的是扩展服务到当前服务的名称。例如web或databases。file指定的是定义有那个service的compose文件。

    如果不指定file选项,compose则在当前文件查找service的配置。file值可以是一个绝对的或相对的路径。如果指定一个相对的路径,这个路径就是相对于当前文件所在目录的路径。

    可以扩展一个本身扩展有另一个的服务。

    external_links

    链接那些在docker-compose.yml外部启动的容器或甚至是在compose外部的,特别是那么提供共享或通用服务的容器。

    external_links在指定容器名称和链接别名(CONTAINER:ALIAS)时遵循类似于链接的语义。

    1. external_links:
    2.  – redis_1
    3.  – project_db_1:mysql
    4.  – project_db_1:postgresql

    注意:如果使用的是version 2文件格式的compose文件,外部创建的容器必须是连接到与链接到它们的服务同处至少一个相同的网络。

    extra_hosts

    添加主机名映射。与docker客户端的–add-host参数作用一样。

    1. extra_hosts:
    2.  – "somehost:162.242.195.82"
    3.  – "otherhost:50.31.209.229"

    这些定义的ip地址和主机条目将在容器内部的/etc/hosts文件里,如:

    1. 162.242.195.82  somehost
    2. 50.31.209.229   otherhost

    image

    指定从其启动容器的镜像。可以是repository/tag或部分镜像ID。

    1. image: redis
    2. image: ubuntu:14.04
    3. image: tutum/influxdb
    4. image: example-registry.com:4000/postgresql
    5. image: a4bc65fd

    如果镜像不存在,compose尝试拉取它,除非也指定了build,在这种情况下它使用指定的选项来构建镜像并使用指定的tag来作标记。

    注意:在version 1文件格式中,不允许build和image一起使用。

    links

    链接到另一个服务的容器。可以指定服务名称和链接别名(SERVICE:ALIAS),或只是服务名称。

    1. web:
    2.   links:
    3.    – db
    4.    – db:database
    5.    – redis

    可以使用与别名一样的主机名访问链接服务的容器,或者如果没有指定别名就使用服务名称。

    链接也以与depends_on相同的方式表示服务之间的依赖关系,因此它们可以决定服务启动的顺序。

    注意:如果定义了links和网络,为了能够通信,链接的服务之间必须至少在一个相同的网络。

    logging

    version 2文件格式或更高版本。在version 1中,使用是的log_driver和log_opt。

    服务的日志配置。

    logging:
    driver: syslog
    options:
    syslog-address: “tcp://192.168.0.42:123”

    driver名称指定一个服务容器的日志驱动,相当于docker run的–log-driver。
    默认的值是json-file。

    1. driver: "json-file"
    2. driver: "syslog"
    3. driver: "none"

    使用options关键词指定日志驱动的日志选项,就像docker run的log-opt选项。

    日志选项是键值对。一个syslog选项的示例:

    1. driver: "syslog"
    2. options:
    3.   syslog-address: "tcp://192.168.0.42:123"

    network_mode

    要求version 2文件格式和之后版本。version 1使用net。

    网络模式。与docker客户端的–net参数一样,加上一个特别的格式service:[service name]。

    1. network_mode: "bridge"
    2. network_mode: "host"
    3. network_mode: "none"
    4. network_mode: "service:[service name]"
    5. network_mode: "container:[container name/id]"

    networks

    要求version 2文件格式和之后版本。version 1使用net。

    要加入的网络,在顶层networks关键词之下引用网络。

    1. services:
    2.   some-service:
    3.     networks:
    4.      – some-network
    5.      – other-network

    aliases

    在网络中服务的别名(替代主机名)。在同一网络的其它容器可以使用服务名称或这个别名来连接服务容器的其中一个。

    因为别名作用域是网络内,所以同一服务在不同的网络可以有不同的别名。

    注意:网络范围的别名可以由多个容器共享,甚至是由多个服务。如果是这样,那么该名称解析到哪个容器将不能保证。

    一般的格式如下:

    1. services:
    2.   some-service:
    3.     networks:
    4.       some-network:
    5.         aliases:
    6.          – alias1
    7.          – alias3
    8.       other-network:
    9.         aliases:
    10.          – alias2

    在下面的示例中,配置了三个服务(web,worker和db)和两个网络(new和legay)。在net网络上可以使用db主机名或database访问db服务,在legacy网络上可以使用db或mysql访问db服务。

    1. version: ‘2’
    2.  
    3. services:
    4.   web:
    5.     build: ./web
    6.     networks:
    7.       – new
    8.  
    9.   worker:
    10.     build: ./worker
    11.     networks:
    12.     – legacy
    13.  
    14.   db:
    15.     image: mysql
    16.     networks:
    17.       new:
    18.         aliases:
    19.           – database
    20.       legacy:
    21.         aliases:
    22.           – mysql
    23.  
    24. networks:
    25.   new:
    26.   legacy:

    ipv4_address, ipv6_address

    加入网络时可以为服务的容器指定静态的IP地址。

    顶层networks区域的相关网络配置必须有一个指定有子网和网关覆盖每个静态地址的配置的ipadm块。如果要使用IPv6地址,必须设置com.docker.network.enable_ipv6驱动选项为true。
    示例:

    1. version: ‘2’
    2.  
    3. services:
    4.   app:
    5.     image: busybox
    6.     command: ifconfig
    7.     networks:
    8.       app_net:
    9.         ipv4_address: 172.16.238.10
    10.         ipv6_address: 2001:3984:3989::10
    11.  
    12. networks:
    13.   app_net:
    14.     driver: bridge
    15.     driver_opts:
    16.       com.docker.network.enable_ipv6: "true"
    17.     ipam:
    18.       driver: default
    19.       config:
    20.       – subnet: 172.16.238.0/24
    21.         gateway: 172.16.238.1
    22.       – subnet: 2001:3984:3989::/64
    23.         gateway: 2001:3984:3989::1

    ports

    暴露端口。可以指定两个端口(HOST:CONTAINER),或只指定一个容器端口(将选择一个随机的主机端口)。

    1. ports:
    2.  – "3000"
    3.  – "3000-3005"
    4.  – "8000:8000"
    5.  – "9090-9091:8080-8081"
    6.  – "49100:22"
    7.  – "127.0.0.1:8001:8001"
    8.  – "127.0.0.1:5000-5010:5000-5010"

    ulimits

    覆盖容器默认的ulimits。可以指定单个限制或soft/hard限制。

    1. ulimits:
    2.   nproc: 65535
    3.   nofile:
    4.     soft: 20000
    5.     hard: 40000

    volumes, volume_driver

    挂载路径或命名数据卷,可选地指定主机的路径(HOST:CONTAINER),或权限模式(HOST:CONTAINER:ro)。对于version 2文件,命名数据卷必须在顶层volumes关键词中指定。当使用version 1时,当命名数据卷不存在时docker engine将会自动创建。

    可以挂载主机的一个相对路径,此路径相对于正在使用的compose文件所在的目录。相对的路径以.或..开头。

    1. volumes:
    2.   # Just specify a path and let the Engine create a volume
    3.   – /var/lib/mysql
    4.  
    5.   # Specify an absolute path mapping
    6.   – /opt/data:/var/lib/mysql
    7.  
    8.   # Path on the host, relative to the Compose file
    9.   – ./cache:/tmp/cache
    10.  
    11.   # User-relative path
    12.   – ~/configs:/etc/configs/:ro
    13.  
    14.   # Named volume
    15.   – datavolume:/var/lib/mysql

    如果不使用主机路径,可能要指定一个volume_driver。

    1. volume_driver: mydriver

    注意,对于version 2文件,这个驱动不会应用到命名数据卷(当声明数据卷时应该使用driver选项)。对于version 1,命名数据卷和容器数据卷使用这个指定的驱动。

    volumes_from

    挂载从另一个服务或容器的所有数据卷,可选地指定只读权限(ro)或读写(rw)。如果没有指定权限级别,将使用读写(rw)权限。

    1. volumes_from:
    2.  – service_name
    3.  – service_name:ro
    4.  – container:container_name
    5.  – container:container_name:rw

    cpu_shares, cpu_quota, cpuset, domainname, hostname, ipc, mac_address, mem_limit, memswap_limit, oom_score_adj, privileged, read_only, restart, shm_size, stdin_open, tty, user, working_dir

    1. cpu_shares: 73
    2. cpu_quota: 50000
    3. cpuset: 0,1
    4.  
    5. user: postgresql
    6. working_dir: /code
    7.  
    8. domainname: foo.com
    9. hostname: foo
    10. ipc: host
    11. mac_address: 02:42:ac:11:65:43
    12.  
    13. mem_limit: 1000000000
    14. memswap_limit: 2000000000
    15. privileged: true
    16.  
    17. oom_score_adj: 500
    18.  
    19. restart: always
    20.  
    21. read_only: true
    22. shm_size: 64M
    23. stdin_open: true
    24. tty: true

    在生产环境使用docker compose

    当在compose定义你的app用于开发环境时,也可以使用这个配置来在不同的环境,如CI,临时和生产环境运行应用程序。

    更改compose文件适用于生产环境

    在把compose部署到生产环境之前,虽然更改你的app配置,这些更改包括:

  • 删除应用程序代码的挂载,以使代码留在容器内,保证无法从外部更改。
  • 绑定不同的主机端口
  • 设置不同的环境变量(如降低日志的详细程序或启用邮件发送)
  • 指定一个重启策略(如restart: always)来避免宕机时间
  • 增加额外的服务(如,日志聚合器)
  • 以上这么多的更改,可以定义一个额外的compose文件,称为production.yml,定义了适合生产环境的配置。这个文件只需要包含你想要对原始文件的更改部分。可以通过原始docker-compose.yml应用额外的Compose文件来创建新配置。

    一旦完成了第二个配置文件的编写,使用-f选项告诉compose使用它:

    1. docker-compose -f docker-compose.yml -f production.yml up -d

    部署更改

    当对你的app代码更改后,需要重建镜像和容器。要重新部署web服务,使用:

    1. $ docker-compose build web
    2. $ docker-compose up –no-deps -d web

    第一个命令重建web的镜像然后停止,销毁和重建web服务。–no-deps选项阻止compose重新创建web信赖的服务。