本地环境是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 ngixn: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 实战经验分享
谢谢谢谢谢~~~~~