摘要:用進(jìn)行操作為在的工作區(qū)域,項(xiàng)目也是掛載在里面,所有我們可以直接在容器里運(yùn)行。或者進(jìn)入宿主機(jī)目錄下用命令注意事項(xiàng)注意掛載路徑構(gòu)建失敗時(shí),注意容器內(nèi)是否報(bào)錯(cuò)加速鏡像。本文首發(fā)在我的博客徒手用構(gòu)建自己的開發(fā)環(huán)境
1. 前言 1.1 為什么要用 Docker ?
是否有這樣的場(chǎng)景,你搞了一個(gè)項(xiàng)目,在本地開發(fā)時(shí)需要搭建環(huán)境,放到線上時(shí)也需要搭建環(huán)境,到公司想暗戳戳玩一下要搭建環(huán)境,不搭還不行,因?yàn)槟愕沫h(huán)境依賴還挺多。這個(gè)時(shí)候如果有了Docker,只需要在機(jī)器上裝個(gè)Docker,放上寫好的Dickerfile,一行命令就自動(dòng)完成這個(gè)事,方便又高效,豈不是很爽?
1.2 準(zhǔn)備接下來,本文介紹如何搭建一個(gè)PHP的開發(fā)環(huán)境,將用 zPhal-dockerfiles 做為例子,這是我為我的博客系統(tǒng)準(zhǔn)備的一套Dockerfile。
現(xiàn)在不管是windows,mac還是linux,docker都可以很好支持,包括Windows系統(tǒng),在win10系統(tǒng)下Docker for Windows 其實(shí)還是挺不錯(cuò)的,就是比較吃內(nèi)存。
通過Docker命令行,我們可以做很多事情,拉取鏡像,運(yùn)行容器,容器內(nèi)執(zhí)行命令等,但是現(xiàn)在,我們要用更加簡(jiǎn)單粗暴的方式,編寫好dockerfiles文件,然后通過docker-compose管理好這些文件,簡(jiǎn)化操作流程。
什么是Dockerfile?
Dockerfile是由一系列命令和參數(shù)構(gòu)成的腳本,這些命令應(yīng)用于拉取的基礎(chǔ)鏡像并最終創(chuàng)建一個(gè)新的鏡像,通過Dockerfile我們可以創(chuàng)建一個(gè)你需要的鏡像,里面是包含了你要安裝的軟件,相當(dāng)于是提前定制好要安裝的拓展,執(zhí)行的命令等,然后一鍵執(zhí)行,極大地簡(jiǎn)化操作流程。
按照本文來搭建環(huán)境,你需要:
首先了解一下Docker以及Docker的一些基本操作,還有docker-compose是什么。
然后需要安裝 Docker 和 docker-compose,我將使用 docker-compose 來管理我的 dockerfiles。
注意,編寫 dockerfile 是活的,不是死的,每個(gè)人寫出來的 dockerfile 都會(huì)不一樣,取決于你的需求。
Docker的官方文檔非常清楚,雖然是英文,但是基本上什么都有,有問題上文檔翻是非常明智的:Docker Documentation
2. 開始編寫接下來都是以 zPhal-dockerfiles 為例子,完整的可以點(diǎn)鏈接進(jìn)去看,下面的只是片段。
2.1 預(yù)覽首先,我們來看一下,我創(chuàng)建的這個(gè)dockerfile項(xiàng)目,我大概分成了下面的目錄(當(dāng)然這個(gè)是自己定的,并不是要求這么去排版你的文件):
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
在這個(gè)項(xiàng)目里,我用到PHP,MySQL,Nginx,Redis;以及Composer,Phalcon拓展等。
總的來說,我們做這件事有三個(gè)流程:編寫好各個(gè)軟件的dockerfile;編寫好配置文件;通過docker-compose處理所有的dockerfile,包括將配置配置文件扔進(jìn)去 dockerfile 文件將構(gòu)建的鏡像中。
2.2 編寫 Dockerfile 文件 2.2.1 PHP下面是PHP的Dockerfile:
FROM php:7.2-fpm MAINTAINER goozp "[email protected]" # 設(shè)置時(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/* # 將預(yù)先下載好的拓展包從宿主機(jī)拷貝進(jìn)去 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ǔ)鏡像,這里我們用了PHP7.2的fpm版本,這里第二行定義了一個(gè)維護(hù)者。
接下來定義了時(shí)區(qū),在每一個(gè)dockerfile都定義了這一句,主要是為了使所有的容器的時(shí)間都與宿主機(jī)同步,其實(shí)我們可以在docker-composer.yml文件中這么定義:
services: php-fpm: volumes: - /etc/localtime:/etc/localtime:ro
但是在非linux系統(tǒng),比如Windows中運(yùn)行時(shí),我們不能取到/etc/localtime,為了更大兼容所有平臺(tái),我把時(shí)間同步寫到dockerfile中。
接下來安裝一些拓展,其實(shí)安裝拓展的過程類似于我們徒手在linux中安裝PHP拓展,值得一提的是composer。我將Composer直接安裝在了php-fpm的鏡像中,其實(shí)官方也提供了Composer的鏡像,拉取composer鏡像執(zhí)行也可以達(dá)到目的,因?yàn)槲覀兪褂胏omposer只是為了執(zhí)行composer命令來管理我們的包,如果composer多帶帶是一個(gè)容器的話,我們?cè)诓挥脮r(shí),還可以將容器關(guān)掉;但是在這里,我直接將composer裝進(jìn)php-fpm鏡像中,主要是我的項(xiàng)目安裝了一些PHP拓展,在編寫composer.json文件時(shí),我定義了extension的依賴,這樣composer執(zhí)行時(shí)會(huì)檢查環(huán)境是否安裝了這些依賴,所有如果我直接用composer鏡像的話,還需要把我用的拓展安裝到鏡像里,就麻煩多了,所以我直接在php鏡像中就把這個(gè)事做了,其實(shí)沒什么區(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
這個(gè)就簡(jiǎn)單多了,我只設(shè)置了一個(gè)時(shí)間。因?yàn)槲也恍枰惭b其它的東西,可以直接使用官方的鏡像。
當(dāng)然,我們需要修改配置文件,只要事先寫好配置文件就行,最后在 docker-compose.yml 文件中,將配置文件扔進(jìn)去,這個(gè)下面會(huì)講,包括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/timezone2.3 編寫配置文件
如何處理配置文件呢,我將配置文件進(jìn)行歸類,PHP的配置文件放在PHP目錄下,Nginx的配置放在Nginx目錄下,至于要不要再新建一個(gè)子文件夾就看情況了,比如conf.d文件夾。
下面以Nginx配置文件為例,首先nginx目錄是這樣的:
nginx/ conf.d/ default.conf zphal.conf Dockerfile nginx.conf
除了nginx.conf外,還有一個(gè)子文件夾conf.d用來存放所有的域名配置文件,在linux下搭建過php環(huán)境的應(yīng)該都比較熟悉。這些配置文件就是我們到時(shí)候要傳進(jìn)去容器中的文件,我們并不會(huì)在宿主機(jī)使用這些文件。
所以需要注意的最重要一點(diǎn)就是,配置文件中出現(xiàn)的路徑是容器內(nèi)環(huán)境的路徑,而不是宿主機(jī)的路徑,每一個(gè)容器內(nèi)都有一個(gè)運(yùn)行環(huán)境,都是一臺(tái)微型小系統(tǒng),這些路徑都是容器內(nèi)的路徑。我們可以通過掛載與容器內(nèi)通訊來同步文件,在命令行啟動(dòng)容器也需要掛載文件路徑,而現(xiàn)在掛載這一步我們也用docker-compose來解決。
下面是一個(gè)配置文件示例:
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路徑,是到時(shí)候nginx容器的路徑,而不是當(dāng)前在操作的宿主機(jī)的路徑,所以到時(shí)候我們要掛載web程序放的位置到這個(gè)路徑。
2.4 編寫 docker-compose.yml在php,nginx等目錄的同級(jí),我們創(chuàng)建一個(gè) docker-compose.yml,我們?cè)趫?zhí)行 docker-compose 相關(guān)命令時(shí),會(huì)自動(dòng)找到這個(gè)文件,并根據(jù)里面的內(nèi)容來執(zhí)行。
接上面 nginx 的例子,我們先談掛載,因?yàn)檫@是最重要的一步。在 docker-compose.yml 中,nginx 的部分:
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;"
有一個(gè) volumes 參數(shù),這里就是我們要掛載的目錄的相關(guān)配置,第一條我們將../app掛載到/data/www之中,也是我們配置文件中定義的默認(rèn)監(jiān)聽的root,而app目錄是我們宿主機(jī)中的一個(gè)目錄,通過這樣掛載我們可以直接將我們的項(xiàng)目文件放到app中,docker會(huì)幫你傳輸?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端口映射到宿主機(jī)的80端口
restart重啟,restart: always表示將自動(dòng)重啟
command是自動(dòng)執(zhí)行的命令
......
參數(shù)很多,更多的可以參考官方文檔。
下面是一個(gè)完整的 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: always3. 使用
這一套編寫下來,我們?cè)趺从媚兀?/p> 3.1 使用搭建好的環(huán)境
首先,進(jìn)入項(xiàng)目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
然后下載我們會(huì)用到的PHP拓展包。
執(zhí)行命令:
docker-compose up
docker會(huì)自動(dòng)通過編寫好的docker-compose.yml內(nèi)容構(gòu)建鏡像,并且啟動(dòng)容器。
如果沒問題,下次啟動(dòng)時(shí)可以以守護(hù)模式啟用,所有容器將后臺(tái)運(yùn)行:
docker-compose up -d
關(guān)閉容器
可以這樣關(guān)閉容器并刪除服務(wù):
docker-compose down
使用 docker-compose 基本上就這么簡(jiǎn)單,用 stop,start 等這些命令來操縱容器服務(wù)。而更多的工作是在于編寫 dockerfile 和 docker-compose.yml 文件。
3.2 使用 Composer當(dāng)我們要使用composer時(shí)怎么做呢? 我們已經(jīng)在php-fpm里安裝了composer。
用 docker-compose 進(jìn)行操作:
docker-compose run --rm -w /data/www/zPhal php-fpm composer update
-w /data/www/zPhal為在php-fpm的工作區(qū)域,zPhal項(xiàng)目也是掛載在里面,所有我們可以直接在容器里運(yùn)行composer。
或者進(jìn)入宿主機(jī)app目錄下用docker命令:
cd zPhal-dockerfiles/app docker run -it --rm -v `pwd`:/data/www/ -w /data/www/zPhal files_php-fpm composer update4. 注意事項(xiàng)
注意掛載路徑
構(gòu)建失敗時(shí),注意容器內(nèi)是否報(bào)錯(cuò)
加速鏡像。如果過程下載鏡像很慢,可以使用國內(nèi)的加速鏡像服務(wù),比如阿里云,Daocloud。
本文首發(fā)在我的博客:徒手用 Docker 構(gòu)建自己的 PHP 開發(fā)環(huán)境
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/28026.html
摘要:用進(jìn)行操作為在的工作區(qū)域,項(xiàng)目也是掛載在里面,所有我們可以直接在容器里運(yùn)行?;蛘哌M(jìn)入宿主機(jī)目錄下用命令注意事項(xiàng)注意掛載路徑構(gòu)建失敗時(shí),注意容器內(nèi)是否報(bào)錯(cuò)加速鏡像。本文首發(fā)在我的博客徒手用構(gòu)建自己的開發(fā)環(huán)境 1. 前言 1.1 為什么要用 Docker ? 是否有這樣的場(chǎng)景,你搞了一個(gè)項(xiàng)目,在本地開發(fā)時(shí)需要搭建環(huán)境,放到線上時(shí)也需要搭建環(huán)境,到公司想暗戳戳玩一下要搭建環(huán)境,不搭還不行,因...
摘要:開場(chǎng)白作為一個(gè)技術(shù)團(tuán)隊(duì)的,你是如何保證成員的開發(fā)環(huán)境達(dá)到公司的標(biāo)準(zhǔn),或者是你定制的最低要求的如果你的回答是差不多就行了,有問題再說,那么,你已經(jīng)在給自己挖坑了。好的,成員們開始構(gòu)建你定制的開發(fā)環(huán)境了。 開場(chǎng)白 作為一個(gè)技術(shù)團(tuán)隊(duì)的Leader,你是如何保證成員的開發(fā)環(huán)境達(dá)到公司的標(biāo)準(zhǔn),或者是你定制的最低要求的?如果你的回答是:差不多就行了,有問題再說,那么,你已經(jīng)在給自己挖坑了。 同事A...
摘要:地址這是一份適用于生產(chǎn)和開發(fā)環(huán)境的。目前已經(jīng)在我司的生產(chǎn)環(huán)境上并運(yùn)行良好。日常開發(fā)中也是基于此鏡像進(jìn)行的。如果想快速看看鏡像里有啥東西,只需要運(yùn)行其中替換成你實(shí)際的鏡像。開發(fā)環(huán)境的使用單獨(dú)運(yùn)行這個(gè)容器是沒有意義的。 GITHUB地址:https://github.com/banyancheu... 這是一份適用于生產(chǎn)和開發(fā)環(huán)境的 Dockerfile。 在 phuison/baseim...
摘要:地址這是一份適用于生產(chǎn)和開發(fā)環(huán)境的。目前已經(jīng)在我司的生產(chǎn)環(huán)境上并運(yùn)行良好。日常開發(fā)中也是基于此鏡像進(jìn)行的。如果想快速看看鏡像里有啥東西,只需要運(yùn)行其中替換成你實(shí)際的鏡像。開發(fā)環(huán)境的使用單獨(dú)運(yùn)行這個(gè)容器是沒有意義的。 GITHUB地址:https://github.com/banyancheu... 這是一份適用于生產(chǎn)和開發(fā)環(huán)境的 Dockerfile。 在 phuison/baseim...
摘要:指令這條命令是指明最后容器需要暴露哪些端口號(hào),這樣其他系統(tǒng)才能使用這個(gè)端口。但是靈活性不高,后面我在編排的時(shí)候會(huì)教大家用編排來統(tǒng)一開發(fā)環(huán)境。更多還有更多指令大家看下官方文檔,我自己覺得上面的指令算是使用比較多的了。 前言 上一篇文章呢,我們簡(jiǎn)單的了解了Docker的基本命令,這篇文章呢,我們來了解下Dockerfile這個(gè)文件。 一個(gè)神奇的文件:Dockerfile 我不知道有多少同學(xué)...
閱讀 2051·2021-11-11 16:54
閱讀 2127·2019-08-30 15:55
閱讀 3626·2019-08-30 15:54
閱讀 402·2019-08-30 15:44
閱讀 2243·2019-08-30 10:58
閱讀 438·2019-08-26 10:30
閱讀 3061·2019-08-23 14:46
閱讀 3216·2019-08-23 13:46