在上一篇文章中,我們知道通過Dockerfile文件可以方便的定義一個單獨的應用鏡像和容器,然而在日常開發中,我們經常會碰到需要多個容器來配合完成某項任務的情況。例如要實現Web服務,需要Nginx、PHP、數據庫等多個容器協作,本文就給大家介紹使用Docker Compose來編排一個LNMP環境。

1.準備環境

系統環境CentOS7.7,Docker版本19.03.6-rc1,docker的搭建過程請參照這篇文章: CentOS Docker安裝

Compose 是用於定義和運行多容器 Docker 應用程序的工具。通過 Compose,我們可以使用 YML 文件來配置應用程序需要的所有服務。然後,使用一個命令,就可以從 YML 文件配置中創建並啓動所有服務。

Docker-compose安裝安裝很簡單,從 Github 上下載它的二進制包來使用,最新發行的版本地址: https://github.com/docker/compose/releases

然後執行以下命令,並查看版本,compose就安裝好了。

mv docker-compose-Linux-x86_64 /usr/local/bin/docker-compose 
chmod +x /usr/local/bin/docker-compose  //設置可執行權限

使用命令 docker-compose --version 查看版本,回顯版本號是1.25.0。

[root@localhost ~]# docker-compose --version
docker-compose version 1.25.0, build 0a186604

2.創建項目目錄

進入/data目錄,創建/lnmp項目目錄,然後在lnmp項目目錄下創建如下項目結構:

[root@localhost lnmp]# tree
.
├── docker-compose.yml          //編排配置文件
├── mariadb                     //MariaDB配置相關目錄
│   ├── conf.d
│   │   └── my.cnf
│   └── logs
├── nginx                       //Nginx配置相關目錄
│   ├── conf.d
│   │   └── default.conf
│   ├── logs
│   └── nginx.conf
├── php                         //PHP配置相關目錄
│   ├── logs
│   ├── php.ini
│   └── www.conf
├── redis                       //Redis配置相關目錄
│   ├── logs
│   └── redis.conf
└── www                         //web訪問目錄
    ├── index.php               //測試phpinfo文件
    ├── mysql.php               //測試mariadb連接文件
    ├── redis.php               //測試redis連接文件
    └── swoole.php              //測試swoole服務文件

3.Docker-compose編排

前面我們講過,通過Compose,我們可以使用一個YML文件來配置應用程序需要的所有服務。在項目lnmp目錄下新建docker-compose.yml文件,內容如下:

version: '3'
networks:
    lnmp-net:
        driver: bridge
services:
    mariadb:
        container_name: mariadb
        image: mariadb:10.4
        ports:
            - 3307:3306
        environment:
            MYSQL_ROOT_PASSWORD: 123456
        volumes:
            - /data/lnmp/mariadb/db:/var/lib/mysql
            - /data/lnmp/mariadb/conf.d:/etc/my.cnf.d
            - /data/lnmp/mariadb/logs:/var/log/mariadb
        restart: always
        networks:
            - lnmp-net
    nginx:
        container_name: nginx
        image: nginx:1.16.1
        ports:
            - 80:80
            - 443:443
        volumes:
            - /data/lnmp/www:/usr/share/nginx/html
            - /data/lnmp/nginx/nginx.conf:/etc/nginx/nginx.conf
            - /data/lnmp/nginx/conf.d:/etc/nginx/conf.d
            - /data/lnmp/nginx/logs:/var/log/nginx
        depends_on:
            - mariadb
            - redis
            - php
        restart: always
        networks:
            - lnmp-net
    php:
        container_name: php
        image: hwphp:7.4-fpm    //自定義鏡像,基於php7.4-fpm,支持Swoole和Redis
        volumes:
            - /data/lnmp/www:/usr/share/nginx/html
            - /data/lnmp/php/php.ini:/usr/local/etc/php/php.ini
            - /data/lnmp/php/logs:/usr/local/var/log
            - /data/lnmp/php/www.conf:/usr/local/etc/php-fpm.d/www.conf
        restart: always
        networks:
            - lnmp-net
    redis:
        container_name: redis
        image: redis:5.0.7
        ports:
            - 6380:6379
        volumes:
            - /data/lnmp/redis/db:/var/lib/redis
            - /data/lnmp/redis/logs:/var/log/redis
        restart: always
        networks:
            - lnmp-net

docker-compose.yml是一個配置文件,該文件是主配置文件,主要包含version、services、network,其中version、services爲必要元素。該配置文件涉及到的指令關鍵字也比較多,不過不要擔心,我們瞭解幾個常用的指令就可以了。

version
networks
services
container_name
image
build
ports
volumes
restart
depends_on
environment

注意,本文中使用的PHP鏡像是作者自定義構建的鏡像 image: hwphp:7.4-fpm ,其中包含了對Swoole和Redis的支持,詳細構建方法請參照本站文站: 使用Docker構建PHP7.4 + Swoole + Redis鏡像 。在services php模塊也可以使用 build 指定的dockerfile自行構建鏡像。格式爲: build: ./php ,然後在項目/php目錄下建立dockerfile文件,內容就是本站上篇文章中的dockerfile文件內容。

4.配置Nginx

我們要讓web服務跑起來,並且支持PHP,需要先定義好Nginx站點配置。

在項目目錄/nginx/conf.d/下新建default.conf文件,內容如下:

server {
        listen 80;
        server_name  "";
         
        index index.html index.htm index.php;
        root /usr/share/nginx/html;
         
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   /usr/share/nginx/html;
        }

        location ~ \.php$ {
            fastcgi_pass   php:9000;  #容器名:端口
            fastcgi_index  index.php;
            fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
            include        fastcgi_params;
        }

        access_log  /var/log/nginx/test.log  main;
 }

我們還可以在該目錄下配置多個.conf文件,以支持多域名站點。

5.啓動服務

現在我們可以啓動服務了,在項目lnmp目錄下(docker-compose.yml所在的目錄)只需一條命令:

docker-compose up -d

執行完畢後會回顯以下信息:

再執行 docker-compose ps 查看服務運行情況:

看到如上圖中各容器的 state全部爲Up 時,我們的Docker服務就通過一鍵啓動全部啓動起來了。

6.驗證結果

現在我們要進行測試,驗證lnmp服務是否正常。

6.1 驗證PHP服務

在項目目錄的www目錄下,建立index.php文件,編輯:

<?php
phpinfo();

然後,在瀏覽器上輸入地址訪問:http://192.168.0.100/index.php,192.168.0.100是宿主機IP。如果正常則會顯示:

6.2 驗證Mariadb服務

在項目目錄的www目錄下,建立mysql.php文件,編輯:

<?php
$dbhost = 'mariadb'; //數據庫服務器,容器名稱
$dbport = 3306; //端口
$dbname = 'hello'; //數據庫名稱
$dbuser = 'root'; //用戶名
$dbpass = '123456'; //密碼

// 連接
try {
    $db = new PDO('mysql:host='.$dbhost.';port='.$dbport.';dbname='.$dbname, $dbuser, $dbpass);
    $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); //設置錯誤模式
    $db->query('SET NAMES utf8;');
    echo 'The connection is successfu.';
} catch(PDOException $e) {
    echo '{"result":"failed", "msg":"連接數據庫失敗!"}';
    exit;
}

注意,連接mariadb時,host設置爲docker的容器名稱,端口爲容器內部端口號3306,並事先建立名爲hello的數據庫,否則會報錯:

Fatal error: Uncaught PDOException: SQLSTATE[HY000] [2002] Connection refused in /usr/share/nginx/html/mysql.php:14

瀏覽器訪問:http://192.168.0.100/mysql.php,顯示:

提示:如果使用其他機器的PHP遠程訪問mysql,請修改配置,使用IP地址和暴露外網的3307端口訪問.

$dbhost = '192.168.0.100'; //數據庫服務器,docker宿主機IP
$dbport = 3307; //端口

6.3 驗證Redis服務

在項目目錄的www目錄下,建立redis.php文件,編輯:

<?php
//連接本地的 Redis 服務
$redis = new Redis();
$redis->connect('redis', 6379);
$redis->auth('123456');
echo "The connection is successfu. 
";

//查看服務是否運行
echo "Server is running: " . $redis->ping();

連接本地的redis,使用redis容器名和6379端口,redis密碼在項目目錄/lnmp/redis/redis.conf文件中設置。

瀏覽器訪問:http://192.168.0.100/mysql.php,顯示:

注意,如果是遠程連接redis,則使用IP和6380端口訪問。

$redis->connect('192.168.0.100', 6380);

6.4 驗證swoole

在項目目錄的www目錄下,建立swoole.php文件,編輯:

<?php
Swoole\Timer::tick(2000, function () {
    echo 'after 2000ms.' . PHP_EOL;
    echo date('Y-m-d H:i:s') . PHP_EOL;
});

以上代碼調用了swoole定時器的功能,每2秒中打印一次信息。在宿主機上,使用Cli命令行模式執行以下命令:

docker exec -it php php /usr/share/nginx/html/swoole.php

回顯如下信息,則swoole服務也正常:

7.附:常用的docker-compose命令

啓動服務: docker-compose up -d --build

停止並卸載服務: docker-compose down

查看容器: docker-compose ps

進入容器: docekr-compose exec $1 $2

$1 docker-compose.yml 文件 services 中定義的服務名稱

$2 根據基礎鏡像服務器決定,一般apline爲 /bin/sh ,其他爲 /bin/bash

相關文章