天天看點

用Docker搭建Laravel開發環境

用Docker搭建Laravel開發環境

在這篇文章中我們将通過Docker在個人本地電腦上建構一個快速、輕量級、不依賴本地電腦所安裝的任何開發套件的可複制的Laravel和Vue項目的開發環境(開發環境的所有依賴都安裝在Docker建構容器裡),加入Vue隻是因為有的項目裡會在Laravel項目中使用Vue做前後端分離開發,開發環境中需要安裝前端開發需要的工具集,當然前後端也可以分成兩個項目開發,這個話題不在本篇文章的讨論範圍内。

是以我們的目标是:

  • 不在本地安裝Mamp/Wamp這樣的軟體
  • 不使用類似Vagrant這樣的虛拟機
  • 不在本地電腦全局安裝PHP開發所需要的工具集
  • 不在本地電腦全局安裝前端開發所需要的工具集
  • 不在本地電腦全局安裝Mysql和Nginx

開始前你需要先去安裝一個Docker用戶端,Docker的官網中有詳細的安裝方法。

第一步:擷取Laravel的源碼包

因為我們電腦上不安裝Composer,是以就不能使用Composer來建立Laravel項目了, 這裡我使用cURL直接從github上下載下傳了最新的Laravel源碼包,你也可以使用wget或者git clone 來擷取源碼包。

curl -L -O  https://github.com/laravel/laravel/archive/v5.5.0.tar.gz /&& tar -zxvf v5.5.0.tar.gz /&& rm v5.5.0.tar.gz           

複制

上面的指令在curl下載下傳完源碼包後會解壓源碼壓縮包,解壓完成後在把源碼壓縮包

v5.8.0.tar.gz

删掉,執行完後你會看到一個laravel-5.8.0的項目目錄。

第二步:添加docker-compose.yml

在項目中建立

docker-compose.yml

檔案。

Compose

項目是 Docker 官方的開源項目,負責實作對 Docker 容器叢集的快速編排。我們知道使用一個

Dockerfile

模闆檔案,可以讓使用者很友善的定義一個單獨的應用容器。在這裡我們會用到四個容器分别将

PHP

Mysql、

Nginx

放在四個不同的容器中,通過

compose`将四個應用容器關聯到一起組成項目。

編排檔案的開頭如下:

version: '2'services:   # our services will go here           

複制

在編排檔案中,把每個容器叫做一個服務,services下定義整個應用中用到的所有服務(即容器)。

App服務

APP服務的容器将執行我們項目中的代碼。

app:  build:    context: ./    dockerfile: app.dockerfile  working_dir: /var/www  volumes:    - ./:/var/www  environment:    - "DB_PORT=3306"    - "DB_HOST=database"           

複制

Notes:

  • 我們使用

    app.dockerfile

    這個鏡像檔案來建構我們的App容器,在鏡像檔案中我們會對項目中用到的PHP子產品鏡像配置,也會額外安裝NPM用來建構前端代碼。
  • working_dir:/var/www

    把工作目錄設定成了

    /var/www

    ,在容器中項目代碼将會被放在

    /var/www

    目錄下面,包括使用

    dockerexecapp

    執行的指令也都是以

    /var/www

    為目前工作目錄的。
  • volumes

    是容器内資料卷所挂載路徑設定,在這裡我們隻定義一個資料卷,把主控端項目目錄挂到在容器中的

    /var/www

    上,這樣我們在本地電腦對項目代碼進行的更改就會馬上同步到容器中去,反過來也是一樣,容器中對代碼做的更改也會及時回報到本地電腦的項目中。
  • environment

    設定環境變量名,這裡我們設定了

    DB_PORT

    DB_HOST

    這樣就不用修改項目中的

    .env

    檔案裡關于這兩項的值了,當然任何你需要在開發環境單獨設定的環境變量都可以寫到這裡,Laravel讀取配置使用的

    DotEnv

    會檢測是否系統有指定環境變量的設定,有的話就不會在去讀取

    .env

    檔案了。

現在我們需要建立上面build環節中提到的

app.dockerfile

這個檔案了,具體内容如下:

FROM php:7.1.22-fpm
# Update packagesRUN apt-get update
# Install PHP and composer dependenciesRUN apt-get install -qq git curl libmcrypt-dev libjpeg-dev libpng-dev libfreetype6-dev libbz2-dev
# Clear out the local repository of retrieved package files# RUN apt-get clean
# Install needed extensions# Here you can install any other extension that you need during the test and deployment processRUN apt-get clean; docker-php-ext-install pdo pdo_mysql mcrypt zip gd pcntl opcache bcmath

# Installs Composer to easily manage your PHP dependencies.RUN curl --silent --show-error https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
# Install NodeRUN apt-get update &&\    apt-get install -y --no-install-recommends gnupg &&\    curl -sL https://deb.nodesource.com/setup_10.x | bash - &&\    apt-get update &&\    apt-get install -y --no-install-recommends nodejs &&\    npm config set registry https://registry.npm.taobao.org --global &&\    npm install --global gulp-cli
CMD php-fpm           

複制

Notes:

  • 我在這裡先将NPM和Composer裝到了app容器中,因為在開發時經常需要執行他們,如果釋出到生産環境,一般是使用單獨的composer對項目代碼進行建構而不是放在運作應用的容器裡,容器的核心思想之一就是保持單一,這樣才能做到快速增加相同角色的容器。

Web服務

接下來,我們需要配置一個Web伺服器用,我們把這個容器在編排檔案中命名成

web

web:  build:    context: ./    dockerfile: web.dockerfile  working_dir: /var/www  volumes_from:    - app  ports:    - 8080:80           

複制

Notes:

  • volumes_from

    用來複用在

    app

    服務中定義的資料卷路徑
  • 通過

    ports

    将本地電腦的8080端口映射到web容器的80端口,這樣在開發環境中我們就不用設定hosts檔案,直接通過IP加端口就能通路服務了。

    Web伺服器選用nginx,是以我們需要用一個nginx鏡像檔案來建構這個容器,在這之前我們需要在nginx鏡像的基礎上再設定一下項目中用到的

    vhost

    ,是以我們需要一個

    web.dockerfile

    檔案,它的定義如下:
FROM nginx:1.10
ADD vhost.conf /etc/nginx/conf.d/default.conf           

複制

根據鏡像檔案的定義,我們把項目中的

vhost.conf

複制到了容器的

/etc/nginx/conf.d/default.conf

中,這樣基本的nginx配置就配置好了,

vhost.conf

中的定義如下:

server {    listen 80;    index index.php index.html;    root /var/www/public;
    location / {        try_files $uri /index.php?$args;    }
    location ~ \.php$ {        fastcgi_split_path_info ^(.+\.php)(/.+)$;        fastcgi_pass app:9000;        fastcgi_index index.php;        include fastcgi_params;        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;        fastcgi_param PATH_INFO $fastcgi_path_info;    }}           

複制

Notes:

  • 因為是開發環境我們就隻進行最簡單的配置,不做調優考慮了。
  • fastcgi_pass app:9000;

    nginx将對PHP的請求通過fastcgi傳遞給了

    app

    服務的9000端口,

    docker-compose

    會自動把services中定義的容器服務連接配接起來,各個服務互相之間使用服務名稱引用。

Mysql服務

接下來我們将配置Mysql服務,與上面兩個服務有點不一樣的是,在PHP-FPM和Nginx的容器中,我們配置本地電腦的檔案可以同步到容器中供容器通路,這讓我們開發時對檔案作的更改能夠快速的在容器中得到回報加快我們的開發過程。但是在資料庫容器中我們希望容器中建立的檔案能夠持久化(預設容器銷毀時,容器内建立的檔案也會被銷毀),我們可以通過Docker的資料卷來實作上述功能,隻不過這次不用再把本地電腦的檔案挂在到資料卷上了,Docker用戶端會管理建立的資料卷的在本地電腦上具體存儲的位置。

下面是編排檔案中對database服務的設定

version: '2'services:
  database:    image: mysql:5.7    volumes:      - dbdata:/var/lib/mysql    environment:      - "MYSQL_DATABASE=homestead"      - "MYSQL_USER=homestead"      - "MYSQL_PASSWORD=secret"      - "MYSQL_ROOT_PASSWORD=secret"    ports:        - "33061:3306"
volumes:  dbdata:           

複制

Notes:

  • 在檔案的最下面我們通過

    volumes

    指令建立了一個名為

    dbdata

    的資料卷(dbdata後面的冒号是有意寫上去的,這是YML檔案的一個文法限制,不用太關心)
  • 定義完資料卷後,在上面我們使用

    <name>:<dir>

    的格式,通知Docker,将

    dbdata

    資料卷挂在到容器中的

    /var/lib/mysql

    目錄上
  • environments

    中設定的是Mysql的docker鏡像需要的四個必要參數。
  • ports

    端口映射中,我們将本地電腦的33061端口映射到容器的3306端口,這樣我們就能通過電腦上的資料庫工具連接配接到docker内的Mysql了。

将所有服務編排到一起

下面是完整的

docker-compose.yml

檔案,通過編排檔案我們将三個應用容器關聯在一起組成了項目的服務端

version: '2'services:
  # The Application  app:    build:      context: ./      dockerfile: app.dockerfile    working_dir: /var/www    volumes:      - ./:/var/www    environment:      - "DB_PORT=3306"      - "DB_HOST=database"
  # The Web Server  web:    build:      context: ./      dockerfile: web.dockerfile    working_dir: /var/www    volumes_from:      - app    ports:      - 8080:80
  # The Database  database:    image: mysql:5.6    volumes:      - dbdata:/var/lib/mysql    environment:      - "MYSQL_DATABASE=homestead"      - "MYSQL_USER=homestead"      - "MYSQL_PASSWORD=secret"      - "MYSQL_ROOT_PASSWORD=secret"    ports:        - "33061:3306"
volumes:  dbdata:           

複制

啟動服務

按照上面的步驟配置好編排檔案還有指定的docker鏡像檔案後,我們就可以通過下面的指令啟動服務了,執行完後會啟動上面檔案裡定義的三個服務。

docker-compose up -d            

複制

第一次啟動時,由于docker用戶端要下載下傳上面提到的三個鏡像并且建構服務是以啟動速度會慢一些,等到下載下傳完鏡像并建構完成後,以後的啟動都會非常快。

初始化Laravel項目

啟動完服務後我們可以初始化Laravel項目了,步驟跟官方文檔裡介紹的一樣,但是需要在啟動的app服務的容器裡執行:

docker-compose exec app composer installdocker-compose exec app npm install // 如果包含前端項目的話再執行相關指令docker-compose exec app cp .env.example .envdocker-compose exec app php artisan key:generatedocker-compose exec app php artisan optimizedocker-compose exec app php artisan migrate --seeddocker-compose exec app php artisan make:controller MyController           

複制

Notes:

  • docker-compose exec 将指令發送到指定的容器中去執行
  • app是定義在docker-compose.yml中的一個服務,它是一個運作着php-fpm的容器
  • php artisan migrate 是要在容器裡執行的指令

檢視nginx日志的方法:

  • docker ps 找到nginx服務的container id
  • docker exec -it /bin/bash 進入nginx容器
  • nginx日志的具體路徑請檢視項目中的vhost.conf

執行完上面的指令後你就能通過

http://127.0.0.1:8080/

通路到項目啦。

用Docker搭建Laravel開發環境

在我的Github gist有一組參考檔案友善同學們參考https://gist.github.com/kevinyan815/fa0760902d29f19a4213b4a16fe0501b

點選下面閱讀原文也可以通路。

gist裡的檔案稍微舊一些,後來在使用的過程中又加入些新的PHP子產品和Node,之前composer也單獨放到了一個容器中,不過相信聰明的你看到這裡應該已經會根據需求更改這些檔案啦。

另外文章裡涉及到的Docker的概念比較多,我這裡收藏了一個寫得很好的Docker給大家參考,作者對Docker的了解卻非常有深度,讓人印象深刻。

https://yeasy.gitbooks.io/docker_practice