PHP Laravel的容器化开发与部署

本文说明一下PHP Laravel(包含Lumen)开发下的Docker化部署,写到了使用 CentOS 6.9、CentOS 7.0 进行生产环境部署,并使用了 Kong 来作为 API 网关进行鉴权。

Docker开发环境

首先,我们需要在开发环境下安装 Docker。这部分网络上的资料汗牛充栋,就不赘述了。

在项目根目录下创建 Dockerfile。 我们使用了 richarvey/nginx-php-fpm 作为基础镜像,相关资料可以查阅其项目文档

FROM richarvey/nginx-php-fpm:1.5.7

RUN sed -i "s/try_files \$uri \$uri\/ =404;/try_files \$uri \$uri\/ \/index.php?\$query_string;/g" /etc/nginx/sites-available/default.conf \
  && sed -i "s/try_files \$uri \$uri\/ =404;/try_files \$uri \$uri\/ \/index.php?\$query_string;/g" /etc/nginx/sites-available/default-ssl.conf \
  && sed -i "s/root \/var\/www\/html/root \/var\/www\/html\/public/g" /etc/nginx/sites-available/default.conf \
  && sed -i "s/root \/var\/www\/html/root \/var\/www\/html\/public/g" /etc/nginx/sites-available/default-ssl.conf

然后创建 docker-compose.yml 文件:

version: '3'
services:

  web:
    build: .
    volumes:
      - .:/var/www/html
    ports:
     - "80:80"
     - "443:443"
    depends_on:
      - redis
      - db
    links:
      - redis
      - db

  redis:
    image: redis

  db:
    image: mysql:5.7
    volumes:
      - ./db_data:/var/lib/mysql
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: password
      MYSQL_DATABASE: appdb
      MYSQL_USER: appuser
      MYSQL_PASSWORD: apppassword

在项目配置 .env 里配置相应的redis和数据库信息:

DB_CONNECTION=mysql
DB_HOST=db
DB_PORT=3306
DB_DATABASE=appdb
DB_USERNAME=appuser
DB_PASSWORD=apppassword

CACHE_DRIVER=redis

REDIS_HOST=redis:6379
REDIS_PORT=6379

然后执行 docker-compose up ,docker会自动构建支持 Laravel 的镜像并将当前项目目录挂载到容器 /var/www/html 目录下。这样就可以在docker环境下进行开发了。

Docker生产镜像

首先修改 .env ,以适配生产环境的相关信息,例如数据库名称、密码等等。这些信息和后面部署时用到的需要一致。

Dockerfile_production:

FROM richarvey/nginx-php-fpm:1.5.7

COPY . /var/www/html/

RUN sed -i "s/try_files \$uri \$uri\/ =404;/try_files \$uri \$uri\/ \/index.php?\$query_string;/g" /etc/nginx/sites-available/default.conf \
  && sed -i "s/try_files \$uri \$uri\/ =404;/try_files \$uri \$uri\/ \/index.php?\$query_string;/g" /etc/nginx/sites-available/default-ssl.conf \
  && sed -i "s/root \/var\/www\/html/root \/var\/www\/html\/public/g" /etc/nginx/sites-available/default.conf \
  && sed -i "s/root \/var\/www\/html/root \/var\/www\/html\/public/g" /etc/nginx/sites-available/default-ssl.conf

使用以下命令构建生产环境镜像:

docker build -t prod_web -f Dockerfile_production .

在CentOS 6.9环境的部署

因为条件所限,有些服务器OS版本比较低(CentOS6.9),安装所需的软件包会比较麻烦,所以需要进行一些升级来运行docker容器环境。

首先升级内核

(从elrepo仓库下载最新的稳定版内核,修改grub.conf以使用最新内核,禁用selinux,然后重启):

rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org
rpm -Uvh http://www.elrepo.org/elrepo-release-6-8.el6.elrepo.noarch.rpm
yum --enablerepo=elrepo-kernel install -y kernel-lt

sed -i 's/default=1/default=0/g' /etc/grub.conf

sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config
sed -i 's/SELINUX=permissive/SELINUX=disabled/g' /etc/selinux/config

reboot

然后安装DOCKER

(安装epel仓库,安装docker-io,设置docker随系统启动并启动docker):

yum -y remove epel-release-6-8
yum -y install http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm

yum install -y docker-io

chkconfig --list | grep docker
chkconfig docker on
service docker start

部署DOCKER镜像

docker-io不支持docker-compose(项目中的 docker-compose.yml 只能用在开发环境或CentOS7上的容器环境),所以镜像只能使用 docker run 来创建容器。

将前面构建的生产环境镜像导出到文件:

docker save -o prod_web.tar prod_web

把镜像上传到CentOS6.9服务器上,导入为本地镜像:

docker load -i prod_web.tar

在CentOS6.9服务器上按顺序执行以下脚本:

  • 1_run_redis.sh:
#!/bin/bash
docker run -it -d --name redis \
  -p 6379:6379 \
  --restart=always \
  redis
  • 2_run_cassandra.sh:
#/bin/bash
docker run --name cassandra \
    -v /data/cassandra:/var/lib/cassandra \
    -d --restart=always\
    -p 9042:9042 \
    cassandra:3
  • init_kong_db.sh: 注意此脚本只应该跑一次
#/bin/bash
docker run --rm \
    --link cassandra \
    -e "KONG_DATABASE=cassandra" \
    -e "KONG_CASSANDRA_CONTACT_POINTS=cassandra" \
    kong:latest kong migrations up
  • 3_run_mysql.sh:
#!/bin/bash
docker run -it -d --name db \
    -v /data/mysql:/var/lib/mysql \
    -e MYSQL_ROOT_PASSWORD=rootpass \
    -e MYSQL_DATABASE=appdb \
    -e MYSQL_USER=appuser \
    -e MYSQL_PASSWORD=apppassword \
    -p 3306:3306 \
    --restart=always \
    mysql:5.7
  • 4_run_prod.sh:
#/bin/bash

mkdir -p /data/prod_storage
chmod -R 777 /data/prod_storage

docker run -it -d --name prod \
    --restart=always \
    -p 8080:80 \
    -v /data/prod_storage:/var/www/storage \
    --link redis:redis \
    --link db:db \
    prod_web
  • 5_run_kong.sh:
#/bin/bash

mkdir -p /data/kong_log

docker run --name kong \
    -d --restart=always \
    -e "KONG_DATABASE=cassandra" \
    -e "KONG_CASSANDRA_CONTACT_POINTS=cassandra" \
    -e "KONG_PROXY_ACCESS_LOG=/data/kong_log/proxy_access.log" \
    -e "KONG_ADMIN_ACCESS_LOG=/data/kong_log/admin_access.log" \
    -e "KONG_PROXY_ERROR_LOG=/data/kong_log/proxy_error.log" \
    -e "KONG_ADMIN_ERROR_LOG=/data/kong_log/admin_error.log" \
    -e "KONG_ADMIN_LISTEN=0.0.0.0:8001, 0.0.0.0:8444 ssl" \
    -p 80:8000 \
    -p 443:8443 \
    -p 8001:8001 \
    -p 8444:8444 \
    -v /data/kong_log:/data/kong_log \
    --link cassandra \
    --link prod \
    kong:latest

后面如果 prod_web 镜像有了修改,我们需要删掉正在运行的 prod 和 kong 两个容器,然后重新导入镜像,创建 prod 和 kong 两个容器:

docker stop prod kong && docker rm prod kong

docker load -i prod_web.tar

./4_run_prod.sh
./5_run_kong.sh

创建 KONG API网关

  • 创建服务 prod-service,注意url里引用的网址是容器名称:
curl -i -X POST \
  --url http://localhost:8001/services/ \
  --data 'name=prod-service' \
  --data 'url=http://prod'

返回类似如下:

{"host":"prod","created_at":1539931317,"connect_timeout":60000,"id":"0dff5819-627e-41d5-8ca0-5fa8c7362d1e","protocol":"http","name":"prod-service","read_timeout":60000,"port":80,"path":null,"updated_at":1539931317,"retries":5,"write_timeout":60000}
  • 为服务 prod-service 创建路由,只要访问域名 prod.test.com,即调用此路由的规则:
curl -i -X POST \
  --url http://localhost:8001/services/prod-service/routes \
  --data 'hosts[]=prod.test.com'

返回类似如下:

{"created_at":1539931349,"strip_path":true,"hosts":["prod.test.com"],"preserve_host":false,"regex_priority":0,"updated_at":1539931349,"paths":null,"service":{"id":"0dff5819-627e-41d5-8ca0-5fa8c7362d1e"},"methods":null,"protocols":["http","https"],"id":"3a38359a-b5b9-482b-8c8e-40fb7f8b70e7"}
  • 为路由添加SSL证书 (这种方式会发生抖动)
curl -i --url http://localhost:8001/certificates \
    --data "cert='-----BEGIN CERTIFICATE-----...'" \
    --data "key='-----BEGIN RSA PRIVATE KEY-----...'" \
    --data "snis[]=prod.test.com"
  • 为服务 prod-service 添加 key-auth 鉴权插件:
curl -i -X POST \
  --url http://localhost:8001/services/prod-service/plugins/ \
  --data 'name=key-auth'

返回类似如下:

{"created_at":1539931369484,"config":{"key_in_body":false,"run_on_preflight":true,"anonymous":"","hide_credentials":false,"key_names":["apikey"]},"id":"9d388bb9-818a-4349-86c0-a7e0cb182978","service_id":"0dff5819-627e-41d5-8ca0-5fa8c7362d1e","name":"key-auth","enabled":true}
  • 添加用户,这里添加了一个用户名为 sdk_007 的用户:
curl -i -X POST \
  --url http://localhost:8001/consumers/ \
  --data "username=sdk_007"

返回类似如下:

{"custom_id":null,"created_at":1539931393,"username":"sdk_007","id":"902fa8f6-feca-4b2d-8e72-d51a86579019"}
  • 为用户 sdk_007 添加用户key:
curl -i -X POST \
  --url http://localhost:8001/consumers/sdk_007/key-auth/

返回类似如下(key已修改):

{"id":"1cc06dcc-0277-4154-a092-c91ff363de92","created_at":1539931418134,"key":"caQVlllch0efVNfGmidadfsa","consumer_id":"902fa8f6-feca-4b2d-8e72-d51a86579019"}
  • 本地测试:
curl 'http://127.0.0.1/<API REQUEST>' --header 'Host: prod.test.com' --header 'apikey: caQVlllch0efVNfGmidadfsa'
  • 在线测试:

使用浏览器打开 http://prod.test.com/<API REQUEST>?apikey=caQVlllch0efVNfGmidadfsa

在CentOS 7环境的部署

首先升级内核

(从elrepo仓库下载最新的稳定版内核,修改grub2以使用最新内核,禁用selinux,然后重启):

rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org
rpm -Uvh https://www.elrepo.org/elrepo-release-7.0-3.el7.elrepo.noarch.rpm
yum --enablerepo=elrepo-kernel install -y kernel-lt

grub2-set-default 0

sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config
sed -i 's/SELINUX=permissive/SELINUX=disabled/g' /etc/selinux/config

reboot

然后安装DOCKER

yum install -y yum-utils device-mapper-persistent-data lvm2
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
yum install -y docker-ce

systemctl enable docker
systemctl start docker

启动容器

同CentOS 6.9

posted @ 2019-01-11 18:01  imthirsty  阅读(1424)  评论(0编辑  收藏  举报