本地環境是mac。使用iTerm2+ohMyZsh
伺服器環境是阿里雲的ecs,綠色純淨centos7一隻.
step1. 透過ssh登上伺服器。配置免密登入。
step2. 伺服器上安裝docker和php(還有git、composer)。
step3. docker分別配置mysql、php、nginx。目標是能正常訪問phpinfo。
step4. 本地安裝deployer。
step5. git相關,建立一個laravel新專案。
step6. 配置deployer部署專案。目標是能正常訪問laravel歡迎頁以及正常使用laravel orm。
哇哦,看著6步,好像蠻少哦,坑超級多- - 一趟趟坑踩下來,快把自己蠢哭了。
step1. 「ssh登伺服器」。
這一步所有操作都在本地,雲伺服器上不做任何改動。登進去後可輸入exit回車退出,也可ctrl+D退出。
阿里雲登上控制檯,雲伺服器ECS檢視示例有個公網ip,就這個公網ip
// 在本地命令列執行
ssh root@{你的雲伺服器公網 IP}
配置免密登入,在ECS管理皮膚中找到金鑰對,點進去,建立金鑰對。
『金鑰對名稱』,我填的是aen233,『建立型別』選擇『自動新建金鑰對』然後點選『確定』按鈕:頁面會彈出一個下載框下載 aen233.pem 檔案,這個檔案需要妥善儲存,我把它放在~/.ssh下面了,配過git ssh的小夥伴應該都知道這個目錄, 同時 SSH 命令要求金鑰的訪問許可權必須是 600。
# 這個我忘記當時走這步沒了,macOS好像木有需要改訪問許可權,如果是Linux就需要改許可權。
chmod 600 ~/.ssh/aen233.pem
這時候可以免密登入了,但是要加 -i 引數
$ ssh root@{你的伺服器公網 IP} -i ~/.ssh/aen233.pem
其中 -i 引數是告知 SSH 要用後面這個檔案作為金鑰登入。不出意外的話會看到詢問是否信任該伺服器,輸入yes,登進。
為了不用每次登入都得加上 -i 引數, 編輯ssh的配置檔案,如果沒有的話,需要新建。
# 本地環境,不是伺服器上的
vim ~/.ssh/config
macOS環境我用的atom編輯器。vim或atom都可以啦,總之編輯成下面這樣
Host {你的雲伺服器公網 IP}
PubkeyAuthentication yes
IdentityFile ~/.ssh/aen233.pem
藍後step1配置完成。
step2. 「伺服器上安裝docker和php」。
這一步操作都在雲伺服器上。
安裝docker
Docker要求64位的系統且核心版本至少為3.10。
執行以下命令。
# 新增yum源。
yum install epel-release –y
yum clean all
yum list
# 安裝並執行Docker。
yum install docker-io –y
systemctl start docker
# 檢查安裝結果。
docker info
安裝php和git、composer
雖然docker也會建立php容器,但是伺服器也需要php,而且必須要求php7.1.3+,因為deployer中的對映目錄在伺服器,不在docker中,這裡就必須要git和composer。
如果php7.0及以下,執行laravel專案的時候,會報laravel require php7.1.3+ 這樣的錯誤。
阿里雲的centos7映象中,php好像還是5.4還是5.6的版本,要先刪掉,愚蠢如我,先下了7.0的版本,報錯,又刪了7.0的版本,安裝了7.2的版本。
解除安裝php
yum list installed | grep php
yum remove php*
安裝php7.2
# 首先獲取rpm:
rpm -Uvh https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
rpm -Uvh https://mirror.webtatic.com/yum/el7/webtatic-release.rpm
# 然後可以利用 sudo yum list php*檢視目前都有php的什麼版本了,可以發現從4-7.2的版本都有,7.2版本名為72w,因此安裝該版本即可:
sudo yum -y install php72w
# 但安裝完畢後,輸入php -v發現並沒有該命令,因為php72w只是安裝了php最小的庫,一些應用還未安裝,因此安裝一些擴充包即可:
yum -y install php72w-cli php72w-common php72w-devel php72w-mysql php72w-mbstring
然後是composer
// 下載composer
curl -sS https://getcomposer.org/installer | php
// 將composer.phar檔案移動到bin目錄以便全域性使用composer命令
mv composer.phar /usr/local/bin/composer
// 切換國內源
composer config -g repo.packagist composer https://packagist.phpcomposer.com
step3. 「docker分別配置mysql、php、nginx」。
雖然有lnmp一鍵包,也有laradock很方便,還是打算分開開,好查錯好維護。
先拉取3個映象:這一步不分順序,3個映象拉取下來備用
// 獲取mysql映象
docker pull mysql:5.7
// 獲取php7.2映象
docker pull php:7.2-fpm
// 拉取nginx映象
docker pull nginx:1.12.2
建立3個容器:注意先後順序,先mysql,再php,最後nginx
# 建立mysql容器
docker run -d -p 3306:3306 -v /var/docker/mysql:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name aen233_mysql mysql:5.7
/* 引數解釋:
-p:埠對映,對映容器的3306. 例如:3307:3306:將容器的3306埠對映到主機的3307埠
-v:/var/docker/mysql:/var/lib/mysql 將主機目錄/var/docker/mysql掛載到容器的目錄/var/lib/mysql,這個目錄是mysql的資料目錄,如果docker容器刪除,資料還在。
-e:MYSQL_ROOT_PASSWORD=123456 初始化root使用者的密碼
-it:執行互動式的容器,讓docker執行的容器實現"對話"的能力
-d:後臺執行容器,並返回容器ID
--name:命名容器
*/
--------------------------------------------------------
# 建立PHPfpm容器
docker run -d -v /var/www/html:/var/www/html -p 9000:9000 --link aen233_mysql:mysql --name aen233_phpfpm php:7.2-fpm
/* 引數解釋:
-v 前面是主機的目錄:對映容器的目錄,這裡需要和nginx容器中一致
--link:掛上msyql。因為php需掛載mysql,所以mysql需要在php之前。
*/
--------------------------------------------------------
# 建立nginx容器
docker run -d -p 80:80 --name aen233_nginx -v /var/www/html:/var/www/html -v /var/docker/nginx/conf.d:/etc/nginx/conf.d --link aen233_phpfpm:phpfpm --name aen233_nginx nginx:1.12.2
/* 引數解釋:
-p:對映80埠
-v:/var/www/html:/var/www/html 這個目錄和php容器中一致。
-v /var/docker/nginx/conf.d:/etc/nginx/conf.d 對映nginx配置目錄,可以不用進docker容器(容器中就不需要安裝vim等),直接在雲伺服器上修改nginx配置。
--name:容器名
--link:跟PHP關聯,所以nginx容器建立要在php容器建立之後。
*/
接下來是配置docker中的mysql、php、nginx。以及測試目錄對映是否生效。
接下來要進入docker容器了
配置mysql 允許遠端登入
這樣就可以在本地透過navicat、SequelPro這些資料庫管理工具登進去了
# 進入容器 (可以用name也可以用容器id)
docker exec -it aen233_mysql bash
# 在容器內登陸mysql
root@74a6c7997285:/ mysql -uroot -p
# 為root分配許可權,以便可以遠端連線
mysql> grant all PRIVILEGES on *.* to root@'%' WITH GRANT OPTION;
mysql> exit;
配置php的擴充套件安裝
# 進入到PHP容器 (可以用name也可以用容器id)
docker exec -it aen233_phpfpm /bin/bash
# php安裝pdo_mysql,不走這一步,laravel會報 can not find driver 錯誤
docker-php-ext-install pdo_mysql(curl ...)
# 要安裝php-redis的話,需要另外下載,執行下面這個命令就可以了,有問就no或者空格就好
pecl install redis && docker-php-ext-enable redis
# 安裝後 php-m 發現就都有了哦
劃重點:安裝之後需要docker restart aen233_phpfpm。
劃重點:安裝之後需要docker restart aen233_phpfpm。
劃重點:安裝之後需要docker restart aen233_phpfpm。
配置Nginx容器,讓他支援PHP
先在雲伺服器修改配置檔案default.conf,如果沒有改檔案就先建立。
# 這個檔案也可以本地寫好,然後透過scp命令傳到雲伺服器上
vi /var/docker/nginx/conf.d/default.conf
基礎的default.conf如下
server {
listen 80;
server_name localhost;
#charset koi8-r;
access_log /var/log/nginx/host.access.log main;
location / {
root /var/www/html;
index index.php index.html index.htm;
# 如果沒有以下4行,laravel將只能訪問首頁,其他頁面都是404
try_files $uri $uri/ /index.php?$query_string;
if (!-e $request_filename){
rewrite ^/(.*) /index.php last;
}
# 如果沒有以上4行,laravel將只能訪問首頁,其他頁面都是404
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
# location ~ \.php$ {
# proxy_pass http://127.0.0.1;
# }
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
location ~ \.php$ {
root /var/www/html;
index index.php index.html;
# 坑在這裡,需將原有的127.0.0.1:9000替換成phpfpm:9000
fastcgi_pass phpfpm:9000;
# 坑在這裡,需將原有的127.0.0.1:9000替換成phpfpm:9000
fastcgi_index index.php;
# 下面這行也改了 中間的$document_root
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}
然後進如nginx容器,敲一個命令“nginx -s reload”,退出即可。
# 進入Nginx容器:
docker exec -it aen233_nginx /bin/bash
# 重新載入Nginx
nginx -s reload
測試目錄對映,訪問phpinfo。
先在雲伺服器的主機 /var/www/html目錄下新建index.php。
<?php
echo phpinfo();
然後瀏覽器輸入你的公網ip,不出意外就是phpinfo頁面啦。
這裡要重點去找pdo,檢視它的mysql是否是enable狀態。
如果你配php擴充套件執行了“docker-php-ext-install pdo_mysql”,但是沒有重啟php容器的話,你在容器中php -m,是能檢視到pdo_mysql擴充套件的,但是在phpinfo中是pdo裡是沒有mysql的。laravel就會報can not find driver 錯誤。
step4. 「本地安裝deployer」
deployer是安裝在本地的。愚蠢如我,第一遍把它裝在伺服器上了
curl -LO https://deployer.org/deployer.phar
mv deployer.phar /usr/local/bin/dep
chmod +x /usr/local/bin/dep
這樣就好了。執行dep 就能看到了
step5.「git相關,建立一個laravel新專案」
首先 要有git賬號、然後要配好ssh key,再然後建立一個倉庫、這個倉庫可以是一個laravel新專案,隨便寫一個路由,控制器的方法中加一行 return User::all();用來測試laravel的orm。
我的專案叫iu。
step6. 「配置deployer部署專案」
建立部署指令碼
在本地macOS中建立一個目錄用於放置部署指令碼:
我建立的目錄在 ~/Sites/deploy-iu
$ cd ~/Sites/deploy-iu
$ dep init
dep init 命令用來建立一個部署指令碼,會詢問我們專案型別,我們是 Laravel 專案所以輸入 1 然後回車;接下來詢問 Repository 也就是我們程式碼倉庫的地址,填入自己的 github 倉庫地址即可。
Deployer 在當前目錄下建立了一個名為 deploy.php 的檔案。
我最終的deploy.php如下。
<?php
namespace Deployer;
require 'recipe/laravel.php';
set('repository', 'https://github.com/aen233/iu.git');
add('shared_files', []);
add('shared_dirs', []);
add('writable_dirs', []);
// 順便把 composer 的 vendor 目錄也加進來
add('copy_dirs', ['node_modules', 'vendor']);
host('111.22.3.4')
->user('root') // 使用 root 賬號登入
->identityFile('~/.ssh/aen233.pem') // 指定登入金鑰檔案路徑
->set('deploy_path', '/var/www/html/iu-deployer'); // 指定部署目錄
// 定義一個上傳 .artisan_env 檔案的任務
desc('Upload .artisan_env file');
task('artisan_env:upload', function() {
// 將本地的 .env 檔案上傳到程式碼目錄的 .env
upload('.artisan_env', '{{release_path}}/.env');
});
// 定義一個上傳 .env 檔案的任務
desc('Upload .env file');
task('env:upload', function() {
// 將本地的 .env 檔案上傳到程式碼目錄的 .env
upload('.env', '{{release_path}}/.env');
});
// 在 deploy:vendors 之前呼叫 deploy:copy_dirs
before('deploy:vendors', 'deploy:copy_dirs');
before('deploy:symlink', 'artisan:migrate');
// 定義一個後置鉤子,在 deploy:shared 之後執行 env:update 任務
after('deploy:shared', 'artisan_env:upload');
after('artisan:migrate', 'env:upload');
after('env:upload', 'artisan:config:cache');
after('artisan:config:cache', 'artisan:route:cache');
after('deploy:failed', 'deploy:unlock');
定義了兩個上傳任務,artisan_env:upload和env:upload,是因為執行migrate時,.env中的DB_HOST=127.0.0.1,但是執行migrate之後,.env的DB_HOST=mysql。
否則laravel會報SQLSTATE[HY000] [2002] Connection refused錯誤。
deploy執行migrate任務時,是在雲伺服器上操作,但是訪問laravel頁面時,是docker中的nginx和php和mysql交流。每個docker執行的容器都是隔離的,這裡的host應該填php容器link的mysql容器。
after('env:upload', 'artisan:config:cache');
在上傳env後,要執行artisan:config:cache。
執行部署命令
藍後 在 ~/Sites/deploy-iu執行:
dep deploy
如果deployer執行composer專案時報錯:
Failed to download laravel/laravel from dist: The zip extension and unzip command are both missing, skipping.
The php.ini used by your command-line PHP is: /etc/php.ini
# 解決辦法: 在伺服器上
yum install zip unzip
藍後需要修改下nginx配置
deployer會將current指向當前部署的程式碼目錄。
# 將default.conf中的兩處root 改成如下
root /var/www/html/iu-deployer/current/public;
訪問頁面,如果是提示沒有許可權。報錯:
The stream or file "/var/www/html/iu/storage/logs/laravel.log" could not be opened: failed to open stream: Permission denied
# 解決辦法:
chmod 777 -R storage/
在iu目錄下,給storage 777許可權
還會遇到的報錯,can not find driver,說過了,php容器要有pdo_mysql擴充套件
SQLSTATE[HY000] [2002] Connection refused,也說過了,.env中的DB_HOST要修改成mysql的docker容器,就是php容器 link的名字。
我自己還遇到一個很想哭的問題,View [welcome] not found. 這個是因為一開始建立容器是,對映的目錄是-v /var/nginx/www/html:/var/www/html,而deployer會把storage共享出來,deployer的配置檔案可能就寫死了/var/nginx/www/html,而nginx訪問的目錄是/var/www/html,所以就找不到了。後來我將伺服器、php、nginx的對映目錄都統一寫成/var/www/html。就好了。
應該可以咯。
phpstorm code + commit + push。
iterm2 執行命令dep deploy。
自動就釋出咯。
參考
參考的教程主要有:
leo 的 電商進階教程 第8章
bestcyt 這篇centos下使用docker搭建lnmp
田勇這篇deployer 實戰經驗分享
謝謝謝謝謝~
本作品採用《CC 協議》,轉載必須註明作者和本文連結