面向生產和開發環境的LNP基礎鏡像

GITHUB地址:https://github.com/banyancheung/base-docker-envphp

這是一份適用於生產和開發環境的 Dockerfile。 在 phuison/baseimage 的基礎上,增長了php、php擴展和nginx的安裝腳本, 實現了一鍵安裝LNP及其經常使用擴展的功能。目前已經在我司的生產環境上並運行良好。平常開發中也是基於此鏡像進行的。mysql

鏡像內容

此鏡像包括以下內容:nginx

  • Ubuntu 16.04 LTS
    • correct init process
    • syslog-ng
    • logrotate
    • SSH server
    • cron
    • runit
    • setuser
    • install_clean

以上這部份內容請移步到 這裏 查看註釋。git

  • re2c-1.0.3
  • php 7.1.18
  • php-swoole-2.2.0
  • php-yaml-2.0.2
  • php-mongodb-1.4.2
  • php-redis-4.0.1
  • php-imagick-3.4.3
  • php-xdebug-2.6.0
  • php-igbinary-2.0.5
  • php-memcached-3.0.4
  • php-yac-2.0.2
  • php-inotify-2.0.0
  • hiredis-0.13.3
  • libmemcached-1.0.18
  • ImageMagick
  • nginx-1.12.2

以上安裝腳本分別在 build/php_7.1.18.shbuild/nginx_1.12.2.sh 中。github

APT這塊使用了清華大學的ubuntu安裝源。 此部分代碼可在 build/prepare.sh 中找到。web

安裝與運行

使用基於docker的開發和生產環境須要你有基礎的docker知識。這裏假設你已經瞭解鏡像,容器,以及容器編排的一些概念而且實際使用過。redis

構建

git clone 此倉庫,在 Dockerfile 所在的目錄執行命令:sql

docker build -t='[ImageName]:[Tag]' .    // [ImageName] 爲你想要的鏡像名稱,若是不想標識版本,請忽略:[Tag]。可是別忽略了"."

而後等待構建成功便可。整個安裝過程約10-15分鐘,取決於你當前所在的網絡環境。mongodb

在線倉庫

若是不想構建,也可使用我已經打包好的在線倉庫。docker

docker pull ccr.ccs.tencentyun.com/qyy-base/qyy-php:1.1.0

運行

經過構建或者在線拉取鏡像到本地後,使用 docker images 查看該鏡像信息。整個鏡像大小爲957MB,運行時佔用內存約300M。

若是想快速看看鏡像裏有啥東西,只須要運行:

docker run --rm -it [ImageID] /sbin/my_init -- bash -l  // 其中ImageID替換成你實際的鏡像ID。

該命令建立容器並啓動了shell,進入交互模式。請注意:鏡像裏面並無運行任何咱們想要的服務(如php和nginx),只是啓動了系統並執行了系統的初始化流程。

開發環境的使用

單獨運行這個容器是沒有意義的。由於這裏面沒有任何你的業務代碼,也沒有任何咱們想要的服務。

下面來看看如何運用在開發環境中:

一個完整的開發環境應當包含數據庫、緩存與web服務。該鏡像已經包含了nginx,因此咱們只須要把其餘的服務跑起來便可。這裏使用到了 docker-compose 把該鏡像與其餘服務連接起來並運行.

咱們應該有一個目錄專門放這些配置文件,假設有個目錄叫 docker-dev,它的目錄結構大概是這個樣子:

docker-dev            部署目錄
├─mysql               數據庫配置目錄
│  ├─my.cnf           公共模塊目錄(可更改)
│  ├─conf.d           模塊目錄(可更改)
│  │  ├─my5.6.cnf     模塊配置文件
│  │  ├─mysqld_safe_syslog.cnf  模塊函數文件
│  │  └─ ...          更多類庫目錄
├─nginx               Nginx配置目錄
│  ├─nginx.conf       要覆蓋的nginx.conf
├─php                 PHP配置目錄
│  ├─php-fpm.conf     要覆蓋的php-fpm conf
│  ├─php-fpm.ini      要覆蓋的php-fpm.ini
│  ├─php.d            擴展配置目錄
│  │  ├─xdebug.ini    要啓用 Xdebug,在該ini文件裏填入 `zend_extension=xdebug.so`
├─redis               緩存配置目錄    
│  ├─redis.conf       要覆蓋的redis.conf
├─docker-compose.yml  docker-compose 編排文件
├─game.sh               業務啓動腳本
├─game.conf             業務的web配置

假設個人業務代碼在 /d/WWW/gamer/game ,是一個基於yii2的php項目。

先來看 docker-compose.yml,注意看註釋:

version: '2'
services:
  php:
    restart: always
    image: ccr.ccs.tencentyun.com/qyy-base/qyy-php:1.1.0
    container_name: game
    volumes:
    - /d/WWW/gamer/game:/home/worker/data/www/game  # 將宿主機的代碼目錄映射到容器的www目錄
    # ... 若是有更多的開發中業務代碼,一併放到這裏並映射到容器 
    - ./php/php-fpm.ini:/home/worker/php/etc/php-fpm.ini # 用開發配置覆蓋容器裏的fpm配置
    - ./php/php-fpm.conf:/home/worker/php/etc/php-fpm.conf # 同上
    - ./php/php.d/xdebug.ini:/home/worker/php/etc/php.d/xdebug.ini # 開發環境開啓xdebug。
    - ./nginx/nginx.conf:/home/worker/nginx/conf/nginx.conf # 用開發配置覆蓋容器裏的nginx配置文件
    - ./game.conf:/home/worker/nginx/conf.d/game.conf  # 業務的nginx配置。
    - ./game.sh:/etc/my_init.d/game.sh # 業務的啓動配置,通常是啓動php-fpm和nginx,也能夠按需寫其餘執行腳本
    # 若是有更多的業務須要自定義腳本或者web,在這裏添加
    ports:
      - "80:80" 
    networks:
      - new
    depends_on:
      - redis
      - memcached
      - mysql
    extra_hosts:
      - "gameapi.cc:192.168.1.9" # 將一個用於開發的虛擬域名指向到宿主機的IP。
  redis:
    restart: always
    image:  registry.cn-hangzhou.aliyuncs.com/qyyteam/redis:1.0.0
    ports:
      - "6379:6379"
    volumes:
      - /d/persistent/redis:/data # 左邊的目錄是我宿主機上的持久化redis存儲目錄,這裏換成本身的。
      - ./redis/redis.conf:/usr/local/etc/redis/redis.conf # 用開發配置覆蓋redis容器裏的配置
    networks:
      - new 
    container_name: redis
  memcached:
    restart: always
    image: registry.cn-hangzhou.aliyuncs.com/qyyteam/memcached:1.0.0
    ports:
      - "11211:11211"
    networks:
      - new 
    container_name: memcached
  mysql:
    image: registry.cn-hangzhou.aliyuncs.com/qyyteam/mysql:5.6
    restart: always
    ports:
      - "3306:3306"
    volumes:
      - ./mysql/my.cnf:/etc/mysql/my.cnf
      - ./mysql/conf.d:/etc/mysql/conf.d
      - /d/server/MySql/data:/var/lib/mysql 
      # 左邊的目錄是我宿主機上的持久化Mysql存儲目錄,這裏換成一個全新的或者已經存在的數據庫目錄。 
    environment:
      - MYSQL_ROOT_PASSWORD=root
      - MYSQL_USER=root
      - MYSQL_PASSWORD=root
    networks:
      - new 
    container_name: mysql
networks:
    new:

如上所示,咱們有php+nginx服務,redis服務、memcached服務,mysql服務。這些服務被編排在一塊兒,合成了一個完整的開發環境。(固然若是你的技術棧不是這樣或者版本不對,能夠換成本身的。這須要你有點動手能力:) )

再來看一下 game.sh :

#!/bin/sh
set -e
mkdir -p /home/worker/data/php/logs/xdebug
# start nginx,php-fpm
setuser worker /home/worker/php/sbin/php-fpm -c /home/worker/php/etc/php-fpm.ini
/home/worker/nginx/sbin/nginx

在docker-compose.yml文件裏,它被映射到了 /etc/my_init.d/ 目錄。在啓動容器的時候該目錄下的shell文件會按文件名順序執行。
該腳本初始化了一個目錄,而且啓動了 php-fpmnginx 用於接收訪問。

最後在docker-compose.yml所在的目錄中,命令輸入:

docker-compose -p dev up -d

便啓動了全部服務。就是這麼簡單!最重要的是,它是一個統一的、可維護的、可在團隊內普及推廣的開發環境!

PS:這個例子的全部代碼會在 example/docker-game-dev 中。

請注意:根據本身實際須要,修改docker-compose.yml或其餘服務如Mysql,redis的配置項,這只是一個例子,千萬不要複製粘貼直接用。

生產環境的使用

其實若是是小公司,業務量不大而且是單機的話,上面的方法裏只須要將配置變量改爲生產環境的就能直接用。

但若是:

  • 是分佈式應用
  • 使用了容器服務(Kubernetes或者swarm)
  • 有CI && CD的需求

就必須把你的業務代碼打包成一個鏡像了。仍是假設項目目錄爲 /d/WWW/gamer/www, 在該目錄下新建一個 Dockerfile :

FROM ccr.ccs.tencentyun.com/qyy-base/qyy-php:1.1.0
MAINTAINER banyan.cheung@gmail.com

# source codes
RUN mkdir -p /home/worker/data/www/game
COPY . /home/worker/data/www/game

# startup scripts
COPY docker/game.sh /etc/my_init.d/game.sh
RUN chmod +x /etc/my_init.d/game.sh

# php-fpm configs
COPY docker/php-fpm.ini /home/worker/php/etc/php-fpm.ini
COPY docker/php-fpm.conf /home/worker/php/etc/php-fpm.conf

# logrotate
COPY docker/nginx /etc/logrotate.d/nginx
COPY docker/php-fpm /etc/logrotate.d/php-fpm
RUN chmod 644 /etc/logrotate.d/nginx
RUN chmod 644 /etc/logrotate.d/php-fpm

EXPOSE 80

這個Dockerfile繼承了基礎鏡像,還作了它獨有的其餘事情:

  • 將代碼Copy進了鏡像裏的www目錄
  • 新增了啓動腳本,替換了原有的php-fpm和ini配置
  • 配置了 logrotate 每隔一段時間分割nginx和php產生的日誌文件

相信你已經觸類旁通了————每個獨立的業務代碼都應該像這樣構建屬於本身的鏡像。構建成功後,就能方便的進行分佈式部署和CI && CD了。

一些文件及路徑的位置

雖然我已經儘量考慮到各類狀況,可是每一個公司每一個團隊的狀況都不同,適用個人不必定適用於你。這裏我列出一些在鏡像裏你可能須要瞭解的地方,以方便你進行定製:

/home/worker/data 目錄是數據目錄,這裏面放一些諸如你的代碼、日誌的東東。

/home/worker/data/www 是固定的web目錄。固然你能夠在 config/php/etc/php-fpm.ini 中修改它。

下面是一些固定的文件路徑:

/home/worker/data/php/logs/php_errors.log php的錯誤日誌

/home/worker/data/php/logs/opcache_errors.log opcache 錯誤日誌

/home/worker/data/php/run/php-fpm.pid php pid 地址。

/home/worker/data/php/logs/php-fpm.log php-fpm 日誌。

/home/worker/data/php/logs/www.access.log access log

以上這些均可以在 config/php/etc/php-fpm.ini 和 config/php/etc/php-fpm.conf 中修改。

php 安裝在 /home/worker/php 中。打開它你會發現熟悉的php安裝目錄。
nginx 安裝在 /home/worker/nginx 中。conf目錄是 /home/worker/nginx/conf.d/

若是須要使用 logrotate , 請寫一個配置文件在Dockerfile裏COPY到 /etc/logrotate.d/,並將權限修改成644。這裏是一個例子:

/etc/logrotate.d/nginx

/home/worker/data/nginx/logs/*.log {
    daily
    missingok
    rotate 7
    compress
    delaycompress
    notifempty
    dateext
    postrotate
        if [ -f /home/worker/data/nginx/logs/nginx.pid ]; then
                kill -USR1 `cat /home/worker/data/nginx/logs/nginx.pid`
        fi
    endscript
}

定時任務能夠寫shell放在 /etc/cron.hourly/,/etc/cron.daily/,/etc/cron.weekly/等文件夾中,系統會根據時間自動執行。 cat /etc/crontab 能夠看到系統自帶的定時任務設置。

若是能幫到你,請到github給我一顆小星星,謝謝 :)

相關文章
相關標籤/搜索