目錄
- 1. 前言
- 2. 開始編寫
- 2.1 預覽
- 2.2 編寫Dockerfile文件
- 2.2.1 PHP
- 2.2.2 Nginx
- 2.2.3 MySQL
- 2.2.4 Redis
- 2.3 編寫配置文件
- 2.4 編寫 docker-compose.yml
- 3. 使用
- 3.1 使用搭建好的環(huán)境
- 3.2 使用Composer
- 4. 注意事項
1. 前言
1.1 為什么要用Docker ?
是否有這樣的場景,你搞了一個項目,在本地開發(fā)時需要搭建環(huán)境,放到線上時也需要搭建環(huán)境,到公司想暗戳戳玩一下要搭建環(huán)境,不搭還不行,因為你的環(huán)境依賴還挺多。這個時候如果有了Docker,只需要在機器上裝個Docker,放上寫好的Dockerfile,一行命令就自動完成這個事,方便又高效,豈不是很爽?
1.2 準備
接下來,本文介紹如何搭建一個PHP的開發(fā)環(huán)境,將用 zPhal-dockerfiles 做為例子,這是我為我的博客系統(tǒng)準備的一套Dockerfile。
現(xiàn)在不管是Windows、Mac還是Linux,Docker都可以很好支持,包括Windows系統(tǒng),在Win 10系統(tǒng)下Docker for Windows 其實還是挺不錯的,就是比較吃內(nèi)存。
通過Docker命令行,我們可以做很多事情,拉取鏡像,運行容器,容器內(nèi)執(zhí)行命令等,但是現(xiàn)在,我們要用更加簡單粗暴的方式,編寫好Dockerfiles文件,然后通過docker-compose管理好這些文件,簡化操作流程。
什么是Dockerfile?
Dockerfile是由一系列命令和參數(shù)構(gòu)成的腳本,這些命令應(yīng)用于拉取的基礎(chǔ)鏡像并最終創(chuàng)建一個新的鏡像,通過Dockerfile我們可以創(chuàng)建一個你需要的鏡像,里面是包含了你要安裝的軟件,相當于是提前定制好要安裝的拓展,執(zhí)行的命令等,然后一鍵執(zhí)行,極大地簡化操作流程。
按照本文來搭建環(huán)境,你需要:
首先了解一下Docker以及Docker的一些基本操作,還有docker-compose是什么。
然后需要安裝Docker和docker-compose,我將使用docker-compose來管理我的Dockerfiles。
注意,編寫Dockerfile是活的,不是死的,每個人寫出來的Dockerfile都會不一樣,取決于你的需求。
Docker的官方文檔非常清楚,雖然是英文,但是基本上什么都有,有問題上文檔翻是非常明智的: Docker Documentation 。
2. 開始編寫
接下來都是以 zPhal-dockerfiles 為例子,完整的可以點鏈接進去看,下面的只是片段。
2.1 預覽
首先,我們來看一下,我創(chuàng)建的這個Dockerfile項目,我大概分成了下面的目錄(當然這個是自己定的,并不是要求這么去排版你的文件):
zPhal-dockerfiles
app/
index.php
phpinfo.php
data/
.gitignore
files/
mysql/
conf.d/
mysql-file.cnf
Dockerfile
nginx/
conf.d/
default.conf
zphal.conf
Dockerfile
nginx.conf
php/
pkg/
.gitignore
Dockerfile
php.ini
php-dev.ini
php-fpm.conf
redis/
Dockerfile
docker-compose.yml
logs/
.gitgnore
README.md
在這個項目里,我用到PHP、MySQL、Nginx、Redis以及Composer、Phalcon拓展等。
總的來說,我們做這件事有三個流程:編寫好各個軟件的Dockerfile;編寫好配置文件;通過docker-compose處理所有的Dockerfile,包括將配置配置文件扔進去Dockerfile文件將構(gòu)建的鏡像中。
2.2 編寫Dockerfile文件
2.2.1 PHP
下面是PHP的Dockerfile:
FROM php:7.2-fpm
MAINTAINER goozp "gzp@goozp.com"
設(shè)置時區(qū)
ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime echo $TZ > /etc/timezone
更新安裝依賴包和PHP核心拓展
RUN apt-get update apt-get install -y \
git \
libfreetype6-dev \
libjpeg62-turbo-dev \
libpng-dev \
docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ \
docker-php-ext-install -j$(nproc) gd \
docker-php-ext-install zip \
docker-php-ext-install pdo_mysql \
docker-php-ext-install opcache \
docker-php-ext-install mysqli \
rm -r /var/lib/apt/lists/*
將預先下載好的拓展包從宿主機拷貝進去
COPY ./pkg/redis.tgz /home/redis.tgz
COPY ./pkg/cphalcon.tar.gz /home/cphalcon.tar.gz
安裝 PECL 拓展,這里我們安裝的是Redis
RUN pecl install /home/redis.tgz echo "extension=redis.so" > /usr/local/etc/php/conf.d/redis.ini
安裝第三方拓展,這里是 Phalcon 拓展
RUN cd /home \
tar -zxvf cphalcon.tar.gz \
mv cphalcon-* phalcon \
cd phalcon/build \
./install \
echo "extension=phalcon.so" > /usr/local/etc/php/conf.d/phalcon.ini
安裝 Composer
ENV COMPOSER_HOME /root/composer
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
ENV PATH $COMPOSER_HOME/vendor/bin:$PATH
RUN rm -f /home/redis.tgz \
rm -f /home/cphalcon.tar.gz
WORKDIR /data
Write Permission
RUN usermod -u 1000 www-data
第一行定義了基礎(chǔ)鏡像,這里我們用了PHP 7.2的fpm版本,這里第二行定義了一個維護者。
接下來定義了時區(qū),在每一個Dockerfile都定義了這一句,主要是為了使所有的容器的時間都與宿主機同步,其實我們可以在docker-composer.yml文件中這么定義:
services:
php-fpm:
volumes:
- /etc/localtime:/etc/localtime:ro
但是在非Linux系統(tǒng),比如Windows中運行時,我們不能取到/etc/localtime,為了更大兼容所有平臺,我把時間同步寫到Dockerfile中。
接下來安裝一些拓展,其實安裝拓展的過程類似于我們徒手在Linux中安裝PHP拓展,值得一提的是Composer。我將Composer直接安裝在了php-fpm的鏡像中,其實官方也提供了Composer的鏡像,拉取Composer鏡像執(zhí)行也可以達到目的,因為我們使用Composer只是為了執(zhí)行Composer命令來管理我們的包,如果Composer單獨是一個容器的話,我們在不用時,還可以將容器關(guān)掉;但是在這里,我直接將Composer裝進php-fpm鏡像中,主要是我的項目安裝了一些PHP拓展,在編寫composer.json文件時,我定義了extension的依賴,這樣Composer執(zhí)行時會檢查環(huán)境是否安裝了這些依賴,所有如果我直接用Composer鏡像的話,還需要把我用的拓展安裝到鏡像里,就麻煩多了,所以我直接在PHP鏡像中就把這個事做了,其實沒什么區(qū)別,取決于你怎么用。
2.2.2 Nginx
下面是Nginx的Dockerfile:
FROM nginx:1.12
set timezome
ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime echo $TZ > /etc/timezone
這個就簡單多了,我只設(shè)置了一個時間。因為我不需要安裝其它的東西,可以直接使用官方的鏡像。
當然,我們需要修改配置文件,只要事先寫好配置文件就行,最后在 docker-compose.yml 文件中,將配置文件扔進去,這個下面會講,包括PHP的配置文件,MySQL的配置文件,都是一樣的。
2.2.3 MySQL
下面是 MySQL 的 Dockerfile:
FROM mysql:5.7
set timezome
ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime echo $TZ > /etc/timezone
MySQL也沒有什么特別之處,直接使用官方的鏡像。
2.2.4 Redis
下面是 Redis 的,也直接使用官方鏡像:
FROM redis:3.2
set timezome
ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime echo $TZ > /etc/timezone
2.3 編寫配置文件
如何處理配置文件呢,我將配置文件進行歸類,PHP的配置文件放在PHP目錄下,Nginx的配置放在Nginx目錄下,至于要不要再新建一個子文件夾就看情況了,比如conf.d文件夾。
下面以Nginx配置文件為例,首先Nginx目錄是這樣的:
nginx/
conf.d/
default.conf
zphal.conf
Dockerfile
nginx.conf
除了nginx.conf外,還有一個子文件夾conf.d用來存放所有的域名配置文件,在Linux下搭建過PHP環(huán)境的應(yīng)該都比較熟悉。這些配置文件就是我們到時候要傳進去容器中的文件,我們并不會在宿主機使用這些文件。
所以需要注意的最重要一點就是,配置文件中出現(xiàn)的路徑是容器內(nèi)環(huán)境的路徑,而不是宿主機的路徑,每一個容器內(nèi)都有一個運行環(huán)境,都是一臺微型小系統(tǒng),這些路徑都是容器內(nèi)的路徑。我們可以通過掛載與容器內(nèi)通訊來同步文件,在命令行啟動容器也需要掛載文件路徑,而現(xiàn)在掛載這一步我們也用docker-compose來解決。
下面是一個配置文件示例:
server {
listen 80 default;
index index.html index.htm;
server_name localhost docker;
root /data/www;
index index.php index.html index.htm;
location / {
try_files $uri $uri/ /index.html;
}
location ~ \.php {
include fastcgi_params;
fastcgi_pass php-fpm:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /data/www/$fastcgi_script_name;
}
}
而root /data/www中,/data/www路徑,是到時候Nginx容器的路徑,而不是當前在操作的宿主機的路徑,所以到時候我們要掛載Web程序放的位置到這個路徑。
2.4 編寫 docker-compose.yml
在PHP、Nginx等目錄的同級,我們創(chuàng)建一個docker-compose.yml,我們在執(zhí)行docker-compose相關(guān)命令時,會自動找到這個文件,并根據(jù)里面的內(nèi)容來執(zhí)行。
接上面Nginx的例子,我們先談掛載,因為這是最重要的一步。在docker-compose.yml中,Nginx的部分:
build: ./nginx
depends_on:
- php-fpm
links:
- php-fpm:php-fpm
volumes:
- ../app:/data/www:rw
- ./nginx/conf.d:/etc/nginx/conf.d:ro
- ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
- ../logs/nginx:/var/log/nginx
ports:
- "80:80"
- "8080:8080"
- "443:443"
restart: always
command: nginx -g 'daemon off;'
有一個volumes參數(shù),這里就是我們要掛載的目錄的相關(guān)配置,第一條我們將../app掛載到/data/www之中,也是我們配置文件中定義的默認監(jiān)聽的root,而APP目錄是我們宿主機中的一個目錄,通過這樣掛載我們可以直接將我們的項目文件放到APP中,Docker會幫你傳輸?shù)饺萜鲀?nèi)的/data/www目錄下。
其它的參數(shù):
build定義了你的Dockerfile在哪里,如果沒有寫Dockerfile可以不用build,可以用images參數(shù)定義官方鏡像,比如image:mysql:5.7;
depends_on表示將依賴其它鏡像,比如Nginx依賴php-fpm,沒有它我Nginx沒法玩;
links定義連接,比如要連接到php-fpm容器,就是php-fpm:php-fpm,后面是別名;
ports表示端口映射,80:80表示將80端口映射到宿主機的80端口;
restart重啟,restart: always表示將自動重啟;
command是自動執(zhí)行的命令;
……
參數(shù)很多,更多的可以參考官方文檔。
下面是一個完整的 docker-compose.yml 文件:
version: '3.2'
services:
php-fpm:
build: ./php/
ports:
- "9000:9000"
links:
- mysql-db:mysql-db
- redis-db:redis-db
volumes:
- ../app:/data/www:rw
- ./php/php-dev.ini:/usr/local/etc/php/php.ini:ro
- ./php/php-fpm.conf:/usr/local/etc/php-fpm.conf:ro
- ../logs/php-fpm:/var/log/php-fpm:rw
restart: always
command: php-fpm
nginx:
build: ./nginx
depends_on:
- php-fpm
links:
- php-fpm:php-fpm
volumes:
- ../app:/data/www:rw
- ./nginx/conf.d:/etc/nginx/conf.d:ro
- ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
- ../logs/nginx:/var/log/nginx
ports:
- "80:80"
- "8080:8080"
- "443:443"
restart: always
command: nginx -g 'daemon off;'
mysql-db:
build: ./mysql
ports:
- "3306:3306"
volumes:
- ../data/mysql:/var/lib/mysql:rw
- ../logs/mysql:/var/lib/mysql-logs:rw
- ./mysql/conf.d:/etc/mysql/conf.d:ro
environment:
MYSQL_ROOT_PASSWORD: 123456
MYSQL_DATABASE: zphaldb
MYSQL_USER: zphal
MYSQL_PASSWORD: zphal123
restart: always
command: "--character-set-server=utf8"
redis-db:
build: ./redis
ports:
- "6379:6379"
volumes:
- ../data/redis:/data
restart: always
3. 使用
這一套編寫下來,我們怎么用呢?
3.1 使用搭建好的環(huán)境
首先,進入項目Dockerfiles的目錄下,這里是files目錄:
cd zPhal-dockerfiles/files
wget https://pecl.php.net/get/redis-3.1.6.tgz -O php/pkg/redis.tgz
wget https://codeload.github.com/phalcon/cphalcon/tar.gz/v3.3.1 -O php/pkg/cphalcon.tar.gz
然后下載我們會用到的PHP拓展包。
執(zhí)行命令:
docker-compose up
Docker會自動通過編寫好的docker-compose.yml內(nèi)容構(gòu)建鏡像,并且啟動容器。
如果沒問題,下次啟動時可以以守護模式啟用,所有容器將后臺運行:
docker-compose up -d
關(guān)閉容器:
可以這樣關(guān)閉容器并刪除服務(wù):
docker-compose down
使用 docker-compose 基本上就這么簡單,用stop,start等這些命令來操縱容器服務(wù)。而更多的工作是在于編寫Dockerfile和docker-compose.yml文件。
3.2 使用Composer
當我們要使用Composer時怎么做呢? 我們已經(jīng)在php-fpm里安裝了Composer。
用docker-compose進行操作:
docker-compose run --rm -w /data/www/zPhal php-fpm composer update
-w /data/www/zPhal為在php-fpm的工作區(qū)域,zPhal項目也是掛載在里面,所有我們可以直接在容器里運行Composer。
或者進入宿主機APP目錄下用Docker命令:
cd zPhal-dockerfiles/app
docker run -it --rm -v `pwd`:/data/www/ -w /data/www/zPhal files_php-fpm composer update
4. 注意事項
注意掛載路徑。
構(gòu)建失敗時,注意容器內(nèi)是否報錯。
加速鏡像。如果過程下載鏡像很慢,可以使用國內(nèi)的加速鏡像服務(wù)。
您可能感興趣的文章:- PyCharm使用Docker鏡像搭建Python開發(fā)環(huán)境
- 利用docker-compose搭建AspNetCore開發(fā)環(huán)境
- 使用Docker快速搭建Oracle開發(fā)環(huán)境的方法教程
- 詳解MAC OSX Docker開發(fā)環(huán)境搭建
- Ubuntu 搭建基于Docker的LNMP+Redis的開發(fā)環(huán)境(圖文)
- 搭建基于Docker的PHP開發(fā)環(huán)境的詳細教程
- 快速掌握使用Docker搭建開發(fā)環(huán)境