使用Docker 一鍵部署 LNMP+Redis 環境

<h1>使用Docker 部署 LNMP+Redis 環境</h1> <h3>Docker 簡介</h3> <p>Docker 是一個開源的應用容器引擎,讓開發者能夠打包他們的應用以及依賴包到一個可移植的容器中,而後發佈到任何流行的 Linux 機器上,也能夠實現虛擬化。容器是徹底使用沙箱機制,相互之間不會有任何接口。推薦內核版本3.8及以上</p> <h3>爲何使用Docker</h3> <ol> <li>加速本地的開發和構建流程,容器能夠在開發環境構建,而後輕鬆地提交到測試環境,並最終進入生產環境</li> <li>可以在讓獨立的服務或應用程序在不一樣的環境中獲得相同的運行結果</li> <li>建立隔離的環境來進行測試</li> <li>高性能、超大規劃的宿主機部署</li> <li>從頭編譯或者擴展示有的OpenShift或Cloud Foundry平臺來搭建本身的PaaS環境</li> </ol> <h2>目錄</h2> <ul> <li><a href="#%E5%AE%89%E8%A3%85Docker">安裝Docker</a></li> <li><a href="#%E7%9B%AE%E5%BD%95%E7%BB%93%E6%9E%84">目錄結構</a></li> <li><a href="#%E5%88%9B%E5%BB%BA%E9%95%9C%E5%83%8F%E4%B8%8E%E5%AE%89%E8%A3%85">快速使用</a></li> <li><a href="#%E8%BF%9B%E5%85%A5%E5%AE%B9%E5%99%A8%E5%86%85%E9%83%A8">進入容器內部</a></li> <li><a href="#PHP%E6%89%A9%E5%B1%95%E5%AE%89%E8%A3%85">PHP擴展安裝</a></li> <li><a href="#Composer%E5%AE%89%E8%A3%85">Composer安裝</a></li> <li><a href="#%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98%E5%A4%84%E7%90%86">常見問題處理</a></li> <li><a href="#%E5%B8%B8%E7%94%A8%E5%91%BD%E4%BB%A4">經常使用命令</a></li> <li><a href="#Dockerfile%E8%AF%AD%E6%B3%95">Dockerfile語法</a></li> <li><a href="#docker-compose%E8%AF%AD%E6%B3%95%E8%AF%B4%E6%98%8E">docker-compose語法說明</a></li> </ul> <blockquote>項目源碼地址:<a href="https://github.com/voocel/docker-lnmp" rel="nofollow noreferrer">GitHub</a> </blockquote> <h3>安裝Docker</h3> <p><strong>windows 安裝</strong></p> <p><a href="http://www.iganlei.cn/environment-configuration/798.html" rel="nofollow noreferrer">參考</a></p> <p><strong>mac</strong></p> <p><a href="https://github.com/widuu/chinese_docker/blob/master/installation/mac.md" rel="nofollow noreferrer">docker toolbox參考</a> </p> <p><strong>linux</strong></p>php

# 下載安裝
curl -sSL https://get.docker.com/ | sh

# 設置開機自啓
sudo systemctl enable docker.service

sudo service docker start|restart|stop

# 安裝docker-compose
curl -L https://github.com/docker/compose/releases/download/1.23.2/docker-compose-`uname -s`-`uname -m` &gt; /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose

<h3>目錄結構</h3>html

docker_lnmp
├── v2
├── mysql
│   └── Dockerfile
│    └── my.cnf
├── nginx
│   ├── Dockerfile
│   ├── nginx.conf
│   ├── log
│   │   └── error.log
│   └── www
│       ├── index.html
│       ├── index.php
│       ├── db.php
│       └── redis.php
├── php
│   ├── Dockerfile
│   ├── www.conf
│   ├── php-fpm.conf
│   ├── php.ini
│   └── log
│       └── php-fpm.log
└── redis
    └── Dockerfile
    └── redis.conf

<h3>建立鏡像與安裝</h3> <blockquote>直接使用docker-compose一鍵製做鏡像並啓動容器</blockquote> <a href="http://www.jqhtml.com/20196.html" target="_blank">docker nginx 部署多個項目</a> <p><strong>版本一</strong></p> <p><em>該版本是經過拉取純淨的CentOS鏡像,經過Dockerfile相關命令進行源碼編譯安裝各個服務。因此該方式很方便定製本身須要的鏡像,可是佔用空間大且構建慢。</em></p>mysql

git clone https://github.com/voocel/docker-lnmp.git
cd docker-lnmp
docker-compose up -d

<p><strong>版本二(推薦)</strong></p>linux

git clone https://github.com/voocel/docker-lnmp.git
cd docker-lnmp/v2
chmod 777 ./redis/redis.log
chmod -R 777 ./redis/data
docker-compose up -d

<p><em>該版本是經過拉取官方已經制做好的各個服務的鏡像,再經過Dockerfile相關命令根據自身需求作相應的調整。因此該方式構建迅速使用方便,由於是基於Alpine Linux因此佔用空間很小。</em></p> <h3>測試</h3> <p>使用docker ps查看容器啓動狀態,若所有正常啓動了則<br>經過訪問127.0.0.一、127.0.0.1/index.php、127.0.0.1/db.php、127.0.0.1/redis.php 便可完成測試<br>(若想使用https則請修改nginx下的dockerfile,和nginx.conf按提示去掉註釋便可,靈須要在ssl文件夾中加入本身的證書文件,本項目自帶的是空的,須要本身替換,保持文件名一致)</p> <h3>進入容器內部</h3> <ol><li>使用 docker exec</li></ol>nginx

docker exec -it ngixn /bin/sh

<ol><li>使用nsenter命令</li></ol>c++

# cd /tmp; curl https://www.kernel.org/pub/linux/utils/util-linux/v2.24/util-linux-2.24.tar.gz | tar -zxf-; cd util-linux-2.24;
# ./configure --without-ncurses
# make nsenter &amp;&amp; sudo cp nsenter /usr/local/bin

<p>爲了鏈接到容器,你還須要找到容器的第一個進程的 PID,能夠經過下面的命令獲取再執行。</p>git

PID=$(docker inspect --format "{{ .State.Pid }}" container_id)
# nsenter --target $PID --mount --uts --ipc --net --pid

<h3>PHP擴展安裝</h3> <ol><li>安裝PHP官方源碼包裏的擴展(如:同時安裝pdo_mysql mysqli pcntl gd四個個擴展)</li></ol> <p><em>在php的Dockerfile中加入如下命令</em></p>github

RUN apk add libpng-dev \
    &amp;&amp; docker-php-ext-install pdo_mysql mysqli pcntl gd \

<p><em>注:由於該鏡像缺乏gd庫所需的libpng-dev包,因此須要先下載這個包</em></p> <ol><li>PECL 擴展安裝</li></ol>web

# 安裝擴展
RUN pecl install memcached-2.2.0 \
    # 啓用擴展
    &amp;&amp; docker-php-ext-enable memcached \

<ol><li>經過下載擴展源碼,編譯安裝的方式安裝</li></ol>redis

# 安裝Redis和swoole擴展
RUN cd ~ \
    &amp;&amp; wget https://github.com/phpredis/phpredis/archive/4.2.0.tar.gz \
    &amp;&amp; tar -zxvf 4.2.0.tar.gz \
    &amp;&amp; mkdir -p /usr/src/php/ext \
    &amp;&amp; mv phpredis-4.2.0 /usr/src/php/ext/redis \
    &amp;&amp; docker-php-ext-install redis \

    &amp;&amp; apk add libstdc++\
    &amp;&amp; cd ~ \
    &amp;&amp; wget https://github.com/swoole/swoole-src/archive/v4.2.12.tar.gz \
    &amp;&amp; tar -zxvf v4.2.12.tar.gz \
    &amp;&amp; mkdir -p /usr/src/php/ext \
    &amp;&amp; mv swoole-src-4.2.12 /usr/src/php/ext/swoole \
    &amp;&amp; docker-php-ext-install swoole \

<p><em>注:由於該鏡像須要先安裝swoole依賴的libstdc++,不然安裝成功後沒法正常加載swoole擴展</em></p> <h3>Composer安裝</h3> <p>在Dockerfile中加入</p> ```RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/bin/ --filename=composer \ ```

<h2>常見問題處理</h2> <ul><li>redis啓動失敗問題</li></ul> <p>在v2版本中redis的啓動用戶爲redis不是root,因此在宿主機中掛載的./redis/redis.log和./redis/data須要有寫入權限。</p>

chmod 777 ./redis/redis.log
   chmod 777 ./redis/data

<ul><li>MYSQL鏈接失敗問題</li></ul> <p>在v2版本中是最新的MySQL8,而該版本的密碼認證方式爲Caching_sha2_password,而低版本的php和mysql可視化工具可能不支持,可經過phpinfo裏的mysqlnd的Loaded plugins查看是否支持該認證方式,不然須要修改成原來的認證方式mysql_native_password:</p>

select user,host,plugin,authentication_string from mysql.user;
    ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY '123456';
    FLUSH PRIVILEGES;

<ul> <li> <p>注意掛載目錄的權限問題,否則容器成功啓動幾秒後馬上關閉,例:如下/data/run/mysql 目錄沒權限的狀況下就會出現剛纔那種狀況</p>

docker run --name mysql57 -d -p 3306:3306 -v /data/mysql:/var/lib/mysql -v /data/logs/mysql:/var/log/mysql -v /data/run/mysql:/var/run/mysqld -e MYSQL_ROOT_PASSWORD=123456 -it centos/mysql:v5.7

</li> <li> <p>須要注意php.ini 中的目錄對應 mysql 的配置的目錄須要掛載才能獲取文件內容,否則php鏈接mysql失敗</p>

# php.ini
mysql.default_socket = /data/run/mysql/mysqld.sock
mysqli.default_socket = /data/run/mysql/mysqld.sock
pdo_mysql.default_socket = /data/run/mysql/mysqld.sock

# mysqld.cnf
pid-file       = /var/run/mysqld/mysqld.pid
socket         = /var/run/mysqld/mysqld.sock

</li> <li> <p>使用php鏈接不上redis</p>

# 錯誤的
$redis = new Redis;
$rs = $redis-&gt;connect('127.0.0.1', 6379);

<p>php鏈接不上,查看錯誤日誌</p>

PHP Fatal error:  Uncaught RedisException: Redis server went away in /www/index.php:7

<p>考慮到docker 之間的通訊應該不能夠用127.0.0.1 應該使用容器裏面的ip,因此查看redis 容器的ip</p>

[root@localhost docker]# docker ps
CONTAINER ID        IMAGE                                COMMAND                  CREATED             STATUS              PORTS                                      NAMES
b5f7dcecff4c        docker_nginx                         "/usr/sbin/nginx -..."   4 seconds ago       Up 3 seconds        0.0.0.0:80-&gt;80/tcp, 0.0.0.0:443-&gt;443/tcp   nginx
60fd2df36d0e        docker_php                           "/usr/local/php/sb..."   7 seconds ago       Up 5 seconds        9000/tcp                                   php
7c7df6f8eb91        hub.c.163.com/library/mysql:latest   "docker-entrypoint..."   12 seconds ago      Up 11 seconds       3306/tcp                                   mysql
a0ebd39f0f64        docker_redis                         "usr/local/redis/s..."   13 seconds ago      Up 12 seconds       6379/tcp                                   redis

<p>注意測試的時候鏈接地址須要容器的ip或者容器名names,好比redis、mysql.<br>例如nginx配置php文件解析 fastcgi_pass php:9000;<br>例如php鏈接redis $redis = new Redis;$res = $redis-&gt;connect('redis', 6379);</p> <p><em>由於容器ip是動態的,重啓以後就會變化,因此能夠建立靜態ip</em></p> <p>第一步:建立自定義網絡</p>

#備註:這裏選取了172.172.0.0網段,也能夠指定其餘任意空閒的網段
docker network create --subnet=172.171.0.0/16 docker-at
docker run --name redis326 --net docker-at --ip 172.171.0.20 -d -p 6379:6379  -v /data:/data -it centos/redis:v3.2.6

<p>鏈接redis 就能夠配置對應的ip地址了,鏈接成功</p>

$redis = new Redis;
$rs = $redis-&gt;connect('172.171.0.20', 6379);

<p>另外還有種可能phpredis鏈接不上redis,須要把redis.conf配置略做修改。</p>

bind 127.0.0.1
改成:
bind 0.0.0.0

</li> <li>啓動docker web服務時 虛擬機端口轉發 外部沒法訪問 通常出如今yum update的時候(WARNING: IPv4 forwarding is disabled. Networking will not work.)或者宿主機能夠訪問,但外部沒法訪問</li> </ul>

vi /etc/sysctl.conf
或者
vi /usr/lib/sysctl.d/00-system.conf
添加以下代碼:
    net.ipv4.ip_forward=1

重啓network服務
systemctl restart network

查看是否修改爲功
sysctl net.ipv4.ip_forward

若是返回爲"net.ipv4.ip_forward = 1"則表示成功了

<ul><li>若是使用最新的MySQL8沒法正常鏈接,因爲最新版本的密碼加密方式改變,致使沒法遠程鏈接。</li></ul>

# 修改密碼加密方式
ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY '123456';

<h3>經常使用命令</h3> <ul> <li> <code>docker start</code> 容器名(容器ID也能夠)</li> <li> <code>docker stop</code> 容器名(容器ID也能夠)</li> <li> <code>docker run</code> 命令加 -d 參數,docker 會將容器放到後臺運行</li> <li> <code>docker ps</code> 正在運行的容器</li> <li> <code>docker logs</code> --tail 10 -tf 容器名 查看容器的日誌文件,加-t是加上時間戳,f是跟蹤某個容器的最新日誌而沒必要讀整個日誌文件</li> <li> <code>docker top</code> 容器名 查看容器內部運行的進程</li> <li> <code>docker exec -d</code> 容器名 touch /etc/new_config_file 經過後臺命令建立一個空文件</li> <li> <code>docker run --restart=always --name</code> 容器名 -d ubuntu /bin/sh -c "while true;do echo hello world; sleep 1; done" 不管退出代碼是什麼,docker都會自動重啓容器,能夠設置 --restart=on-failure:5 自動重啓的次數</li> <li> <code>docker inspect</code> 容器名 對容器進行詳細的檢查,能夠加 --format='{(.State.Running)}' 來獲取指定的信息</li> <li> <code>docker rm</code> 容器ID 刪除容器,注,運行中的容器沒法刪除</li> <li> <code>docker rm $(docker ps -aq)</code> 刪除全部容器</li> <li> <code>docker rmi $(docker images -aq)</code> 刪除全部鏡像</li> <li> <code>docker images</code> 列出鏡像</li> <li> <code>docker pull</code> 鏡像名:標籤 拉鏡像</li> <li> <code>docker search</code> 查找docker Hub 上公共的可用鏡像</li> <li> <code>docker build -t='AT/web_server:v1'</code> 命令後面能夠直接加上github倉庫的要目錄下存在的Dockerfile文件。 命令是編寫Dockerfile 以後使用的。-t選項爲新鏡像設置了倉庫和名稱:標籤</li> <li> <code>docker login</code> 登錄到Docker Hub,我的認證信息將會保存到$HOME/.dockercfg,</li> <li> <code>docker commit -m="comment " --author="AT" </code> 容器ID 鏡像的用戶名/倉庫名:標籤 不推薦這種方法,推薦dockerfile</li> <li> <code>docker history</code> 鏡像ID 深刻探求鏡像是如何構建出來的</li> <li> <code>docker port</code> 鏡像ID 端口 查看映射狀況的容器的ID和容器的端口號,假設查詢80端口對應的映射的端口</li> <li> <code>run</code> 運行一個容器, -p 8080:80 將容器內的80端口映射到docker宿主機的某一特定端口,將容器的80端口綁定到宿主機的8080端口,另 127.0.0.1:80:80 是將容器的80端口綁定到宿主機這個IP的80端口上,-P 是將容器內的80端口對本地的宿主機公開</li> <li> <a href="http://docs.docker.com/reference/builder/" rel="nofollow noreferrer">http://docs.docker.com/refere...</a> 查看更多的命令</li> <li> <code>docker push</code> 鏡像名 將鏡像推送到 Docker Hub</li> <li> <code>docker rmi</code> 鏡像名 刪除鏡像</li> <li> <code>docker attach</code> 容器ID 進入容器</li> <li> </li> <li> <code>docker network create --subnet=172.171.0.0/16 docker-at</code> 選取172.172.0.0網段</li> <li> <code>docker build</code> 就能夠加 -ip指定容器ip 172.171.0.10 了</li> </ul> <p><strong>刪除全部容器和鏡像的命令</strong></p>

docker rm `docker ps -a |awk '{print $1}' | grep [0-9a-z]` 刪除中止的容器
docker rmi $(docker images | awk '/^&lt;none&gt;/ { print $3 }')

<h3>Dockerfile語法</h3> <ul> <li> <code>MAINTAINER</code> 標識鏡像的做者和聯繫方式</li> <li> <code>EXPOSE</code> 能夠指定多個EXPOSE向外部公開多個端口,能夠幫助多個容器連接</li> <li> <code>FROM</code> 指令指定一個已經存在的鏡像</li> <li> <code>\#</code>號表明註釋</li> <li> <code>RUN</code> 運行命令,會在shell 裏使用命令包裝器 /bin/sh -c 來執行。若是是在一個不支持shell 的平臺上運行或者不但願在shell 中運行,也能夠 使用exec 格式 的RUN指令</li> <li> <code>ENV REFRESHED_AT</code> 環境變量 這個環境亦是用來代表鏡像模板最後的更新時間</li> <li> <code>VOLUME</code> 容器添加捲。一個卷是能夠 存在於一個或多個容器內的特定的目錄,對卷的修改是馬上生效的,對卷的修改不會對更新鏡像產品影響,例:VOLUME["/opt/project","/data"]</li> <li> <code>ADD</code> 將構建環境 下的文件 和目錄複製到鏡像 中。例 ADD nginx.conf /conf/nginx.conf 也能夠是取url 的地址文件,若是是壓縮包,ADD命令會自動解壓、</li> <li> <code>USER</code> 指定鏡像用那個USER 去運行</li> <li> <code>COPY</code> 是複製本地文件,而不會去作文件提取(解壓包不會自動解壓) 例:COPY conf.d/ /etc/apache2/ 將本地conf.d目錄中的文件複製到/etc/apache2/目錄中</li> </ul> <h3>docker-compose.yml 語法說明</h3> <ul> <li> <code>image</code> 指定爲鏡像名稱或鏡像ID。若是鏡像不存在,Compose將嘗試從互聯網拉取這個鏡像</li> <li> <code>build</code> 指定Dockerfile所在文件夾的路徑。Compose將會利用他自動構建這個鏡像,而後使用這個鏡像</li> <li> <code>command</code> 覆蓋容器啓動後默認執行的命令</li> <li> <code>links</code> 連接到其餘服務容器,使用服務名稱(同時做爲別名)或服務別名(SERVICE:ALIAS)均可以</li> <li> <code>external_links</code> 連接到docker-compose.yml外部的容器,甚至並不是是Compose管理的容器。參數格式和links相似</li> <li> <code>ports</code> 暴露端口信息。宿主機器端口:容器端口(HOST:CONTAINER)格式或者僅僅指定容器的端口(宿主機器將會隨機分配端口)均可以(注意:當使用 HOST:CONTAINER 格式來映射端口時,若是你使用的容器端口小於 60 你可能會獲得錯誤得結果,由於 YAML 將會解析 xx:yy 這種數字格式爲 60 進制。因此建議採用字符串格式。)</li> <li> <code>expose</code> 暴露端口,與posts不一樣的是expose只能夠暴露端口而不能映射到主機,只供外部服務鏈接使用;僅能夠指定內部端口爲參數</li> <li> <code>volumes</code> 設置卷掛載的路徑。能夠設置宿主機路徑:容器路徑(host:container)或加上訪問模式(host:container:ro)ro就是readonly的意思,只讀模式</li> <li> <code>volunes_from</code> 掛載另外一個服務或容器的全部數據卷</li> <li> <code>environment</code> 設置環境變量。能夠屬於數組或字典兩種格式。若是隻給定變量的名稱則會自動加載它在Compose主機上的值,能夠用來防止泄露沒必要要的數據</li> <li> <code>env_file</code> 從文件中獲取環境變量,能夠爲單獨的文件路徑或列表。若是經過docker-compose -f FILE指定了模板文件,則env_file中路徑會基於模板文件路徑。若是有變量名稱與environment指令衝突,則之後者爲準(環境變量文件中每一行都必須有註釋,支持#開頭的註釋行)</li> <li> <code>extends</code> 基於已有的服務進行服務擴展。例如咱們已經有了一個webapp服務,模板文件爲common.yml。編寫一個新的 development.yml 文件,使用 common.yml 中的 webapp 服務進行擴展。後者會自動繼承common.yml中的webapp服務及相關的環境變量</li> <li> <code>net</code> 設置網絡模式。使用和docker client 的 --net 參數同樣的值</li> <li> <code>pid</code> 和宿主機系統共享進程命名空間,打開該選項的容器能夠相互經過進程id來訪問和操做</li> <li> <code>dns</code> 配置DNS服務器。能夠是一個值,也能夠是一個列表</li> <li> <code>cap_add,cap_drop</code> 添加或放棄容器的Linux能力(Capability)</li> <li> <code>dns_search</code> 配置DNS搜索域。能夠是一個值也能夠是一個列表</li> <li>注意:使用compose對Docker容器進行編排管理時,須要編寫docker-compose.yml文件,初次編寫時,容易遇到一些比較低級的問題,致使執行docker-compose up時先解析yml文件的錯誤。比較常見的是yml對縮進的嚴格要求。yml文件還行後的縮進,不容許使用tab鍵字符,只能使用空格,而空格的數量也有要求,通常兩個空格。</li> </ul> <blockquote>項目源碼地址:<a href="https://github.com/voocel/docker-lnmp" rel="nofollow noreferrer">GitHub</a> </blockquote>

來源:https://segmentfault.com/a/1190000017844566

相關文章
相關標籤/搜索