小白折腾服务器(一):docker 搭建 lnmp+ 使用 deployer 部署

本地环境是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 协议》,转载必须注明作者和本文链接
本帖由系统于 5年前 自动加精
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
讨论数量: 10

先下了7.0的版本,报错,又删了7.0的版本,安装了7.2的版本。不能安装2个版本吗?

/var/lib/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
5年前 评论
m01i0ng

@lovecn 两个版本 php 会冲突、如果希望使用多版本切换可以找下 phpbrew 这个工具。
对于 mysql 各个版本镜像来说这个目录是固定的

5年前 评论

@Alley soga,谢谢啦

5年前 评论

@lovecn 报错是在执行dep deploy命令时,composer报laravel reqiure php 7.1.3+,我当时想到最简单的办法就是先删了服务器上7.0版本的,装个7.1+的,我主要是折腾docker+deploy的,根本就没想着弄多版本php

5年前 评论
黑将军

step1完全可以省略,阿里云控制台直接可以部署公钥,只要在你本地部署好私钥就行

5年前 评论

大腿 空着么?我要抱着

5年前 评论

@truncate_xiaoxing123 我还是小白一枚,你有问题直接问,我会的话肯定讲,社区里大家也都会帮你哒

5年前 评论

@ykun 兄弟你把docker安装好了么

4年前 评论

@aen233

docker info

Containers: 0
Running: 0
Paused: 0
Stopped: 0
Images: 0
Server Version: 1.13.1
Storage Driver: overlay2
Backing Filesystem: extfs
Supports d_type: true
Native Overlay Diff: true
Logging Driver: journald
Cgroup Driver: systemd
Plugins:
Volume: local
Network: bridge host macvlan null overlay
Swarm: inactive
Runtimes: docker-runc runc
Default Runtime: docker-runc
Init Binary: /usr/libexec/docker/docker-init-current
containerd version: (expected: aa8187dbd3b7ad67d8e5e3a15115d3eef43a7ed1)
runc version: df5c38a9167e87f53a9894d77c0950e178a745e7 (expected: 9df8b306d01f59d3a8029be411de015b7304dd8f)
init version: fec3683b971d9c3ef73f284f176672c44b448662 (expected: 949e6facb77383876aeff8a6944dde66b3089574)
Security Options:
seccomp
WARNING: You're not using the default seccomp profile
Profile: /etc/docker/seccomp.json
Kernel Version: 3.10.0-957.1.3.el7.x86_64
Operating System: CentOS Linux 7 (Core)
OSType: linux
Architecture: x86_64
Number of Docker Hooks: 3
CPUs: 1
Total Memory: 1.952 GiB
Name: instance-d69ikzob
ID: KL3T:LGDL:2GUG:3XIB:SMO2:6ASN:D42B:HU4Y:P5IG:YOFW:VRMR:DZEA
Docker Root Dir: /var/lib/docker
Debug Mode (client): false
Debug Mode (server): false
Registry: https://index.docker.io/v1/
Experimental: false
Insecure Registries:
127.0.0.0/8
Live Restore Enabled: false
Registries: docker.io (secure)

4年前 评论

不懂就问,请问那个deployer和github的webhook是不是差不多

2年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!
php @ abc
文章
20
粉丝
94
喜欢
197
收藏
231
排名:107
访问:8.9 万
私信
所有博文
社区赞助商