将新项目接入Laravel Sail 创建好的MySQL、Redis容器,并实现自己的 sail 脚本与容器交互
自发布 《将 Laravel 开发环境由 Homestead 迁移到 Laravel Sail ( Docker ) 完整详细教程》 这篇文章以来,已经有 1900 多个阅读了,看来大家都在积极拥抱 Laravel Sail 开发环境,开始逐步淘汰 Homestead。
Laravel Sail 开发环境仅支持 Laravel8 及以上版本,很多老一点的项目是基于5 - 7版本的。对于这些项目,我们只要自己构建一个 PHP 运行容器接入 Laravel Sail 创建好的 MySql、 Redis等容器,然后写一个 shell 脚本(my-sail.sh)与容器交互,我们就将开发环境都统一成 Laravel Sail 了。
当然,即使是基于 laravel8 的新项目,你可能不愿意再次搭建和编排新的MySQL、Redis 容器,或者多个项目之间需要使用相同的 MySQL、Redis 容器,这篇文章都适合你。
对于有 Linux 基础和 Docker 基础的人来说,自己完全可以独立构建镜像并编排运行容器。但对于很多 Linux 和 Docker 知识不是很牢靠的开发者而言,写一篇简单易懂的入门接入教程还是很有必要的。让我们开始吧,假如我们现在有一个基于 Laravel7 开发的应用 Leona,我们将从拉取项目代码开始,一步一步接入已经通过 Laravel Sail 构建好的MySQL、Redis容器。
前提条件
已经通过教程构建好了 Laravel Sail 开发环境,并且已经具有了至少一个 搭建好的Laravel Sail 服务,没有构建好环境的朋友请参考文章开头提到的文章。首先打开 Docker Desktop,启动提前构建好的Laravel Sail 服务,笔者这里是kkyn_dcat_admin
:
拉取项目源码
进入 Ubuntu 子系统的项目目录\\wsl$\Ubuntu\home\myhui\projects
,拉取项目源码:
git clone git@gitee.com:xxxxx/leona.git
注意:这里需要拉取你自己的源码
用 IDE(PhpStorm) 打开项目
同样,为了更快的运行速度,我们将项目放在 Ubuntu 子系统内部:
修改自己的 hosts 文件,配置开发域名
# 192.168.10.10 leona.test
127.0.0.1 leona.test
注意:如果之前你的开发域名是解析到 Homestead 的IP地址,必须把 Homestead 的IP解析注释掉或直接删除,否则会导致应用运行十分卡顿,参考《记一次 hosts 文件配置错误导致应用卡顿的奇葩问题》
配置 .env 环境变量文件:
回到项目 IDE 界面,打开 Terminal ,创建 .env 环境配置文件:
cp .env.example .env
为了小白不犯错,放个截图:
参考以下的环境变量(.env)配置,配置你自己的 .env 文件:
APP_NAME=Leona
APP_ENV=local
APP_KEY=
APP_DEBUG=true
DOCKER_PORT=9233 #Docker容器映射出来的端口
APP_URL="http://leona.test:${DOCKER_PORT}" #应用地址
# Docker容器相关的环境变量
WWWUSER=1000 #运行id命令查看自己的 uid 和 gid
WWWGROUP=1000
MYSQL_CONTAINER_NAME=kkyn_dcat_admin_mysql_1 #需要接入的数据库容器的名称,这里要改成你自己的
DOCKER_NETWORK=kkyn_dcat_admin_sail #之前构建好的 Sail 服务的network,这里改成你自己的
DOCKER_CONTAINER_NAME=leona #当前应用的容器名称
# 数据库配置
DB_CONNECTION=mysql
DB_HOST=mysql
DB_PORT=3306
DB_DATABASE=leona
DB_USERNAME=root #为了避免不必要的麻烦,使用root账号
DB_PASSWORD=kkyn #root账号的密码与 Laravel-Sail 中 docker-compose.yml 中的 "MYSQL_ROOT_PASSWORD" 配置相同
# Redis配置
REDIS_HOST=redis
REDIS_PASSWORD=null
REDIS_PORT=6379
REDIS_CLIENT=phpredis
注意: 为了我们新构建的容器接入之前已经构建好的 MySQL 与 Redis 容器,需要让新容器与之前构建好的 Sail 服务处于同一网络下,运行以下命令查看自己的 Docker 网络:
docker network ls
复制自己的网络名称,写到 .env 文件的
DOCKER_NETWORK
项:
同时为了能够在 MySQL 容器内自动创建所需的数据库,需要知道之前构建好的 MySQL 容器的名称,可以通过 Docker Desktop 查看自己的 MySQL 容器名称,并将容器名称配置给MYSQL_CONTAINER_NAME
环境变量:
写一个简易的 sail 脚本
为了方便我们构建容器并与容器交互,我们参照 Laravel Sail 的实现方式,写一个自己的简易 sail。
大家都知道,Laravel Sail 的核心就是./vendor/laravel/sail/bin/sail
文件,这是一个方便我们使用 Docker 的 shell 脚本文件,我们参考这个 shell 脚本文件。写一个简单的 my-sail.sh
文件,方便我们构建容器并与容器交互。
新建 my-sail.sh 文件
打开 PhpStorm,在项目目录(~/projects/leona
)下新建 my-sail.sh
文件,脚本内容我已经写好了,你只需要将以下内容复制粘贴进去:
#!/usr/bin/env bash
# 定义终端显示字体的颜色
WHITE='\033[0;37m'
NC='\033[0m'
RED='\033[0;31m'
GREEN='\033[0;32m'
BLUE='\033[0;34m'
YELLOW='\033[1;33m'
# 将.env文件中的配置项导入当前脚本,相当于定义了与环境变量 key 同名的shell变量
# shellcheck source=.env
source .env
# 当前目录的路径
CURRENT_DIR="$(pwd)"
# 设置shell脚本运行的用户名与用户组环境变量,如果环境变量文件内没有配置,则使用运行脚本的当前用户属性
export WWWUSER=${WWWUSER:-$UID}
export WWWGROUP=${WWWGROUP:-$(id -g)}
# 创建数据库
create_database(){
echo "正在创建数据库..."
docker exec -i "${MYSQL_CONTAINER_NAME}" /bin/bash <<EOF
mysql -u${DB_USERNAME} -p${DB_PASSWORD}
CREATE DATABASE ${DB_DATABASE} CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
exit
EOF
printf "${GREEN}%s\n" "数据库${DB_DATABASE}创建成功"
}
# 创建容器函数
run_container(){
echo "正在安装依赖..."
composer install
echo "生成APP_KEY..."
php artisan key:generate
printf "${NC} %s\n" "正在创建容器: ${DOCKER_CONTAINER_NAME} ..."
docker run --name "${DOCKER_CONTAINER_NAME}" \
-v "${CURRENT_DIR}":/var/www/html \
-p "${DOCKER_PORT}":80 -d \
-e WWWUSER=${WWWUSER} \
--entrypoint start-container \
--network "${DOCKER_NETWORK}" \
sail-7.4/app
printf "${GREEN}%s\n" "容器创建完成"
}
if [ "$1" = "run" ]; then
# 创建数据库
if [ "$2" = "--with-database" ]; then
create_database
fi
# 创建容器
run_container
# 执行数据迁移
if [ "$2" = "--with-database" ]; then
echo "执行数据迁移..."
docker exec -u sail -it "${DOCKER_CONTAINER_NAME}" /bin/bash -c "php artisan migrate --seed"
fi
# 系统访问地址
printf "${NC}%s${GREEN}%s\n" "系统访问地址:" "${APP_URL}"
elif [ "$1" = "start" ]; then
# 启动容器:
echo "正在启动..."
docker start "${DOCKER_CONTAINER_NAME}"
printf "${NC} %s ${BLUE} %s\n" "系统访问地址:" "${APP_URL}"
printf "${GREEN} %s \n" "启动成功!"
elif [ "$1" = "enter" ]; then
# 进入容器:
docker exec -it "${DOCKER_CONTAINER_NAME}" /bin/bash
elif [ "$1" = "stop" ]; then
# 停止容器:
echo "正在停止..."
docker stop "${DOCKER_CONTAINER_NAME}"
echo "已停止!"
elif [ "$1" = "restart" ]; then
# 重启容器
echo "正在重启..."
docker restart "${DOCKER_CONTAINER_NAME}"
printf "${GREEN}%s\n" "重启成功!"
elif [[ "$1" == "composer"* ]]; then
# 在容器内执行 composer 命令
docker exec -u sail -i "${DOCKER_CONTAINER_NAME}" /bin/bash <<EOF
if [ "$(composer config -g -l | grep 'aliyun')" = '' ]; then
composer config -g repo.packagist composer https://mirrors.aliyun.com/composer
fi
$*
EOF
else
# 在容器内执行命令:
docker exec -u sail -it "${DOCKER_CONTAINER_NAME}" /bin/bash -c "$*"
fi
如果你想知道具体的实现原理,请参考代码注释,需要你熟悉 Docker 与 shell 脚本编程。
为脚本赋予可执行权限
在 Terminal 内,定位到项目目录下,执行以下命令:
chmod a+x my-sail.sh
构建容器
执行以下命令构建容器并同时创建数据库:
./my-sail.sh run --with-database
如果只构建容器,去掉 --with-database
参数即可:
./my-sail.sh run
看到以下界面,说明构建成功了:
将系统访问地址复制到浏览器打开,如果看到 Laravel 界面,说明运用运行环境创建成功了:
使用 my-sail 与容器交互
创建数据库迁移
./my-sail.sh php artisan make:migration create_test_table
运行结果:
查看PHP版本
./my-sail.sh php -v
运行结果
tinker终端
./my-sail.sh php artisan tinker
总之,就是需要在容器环境执行的命令,通通在前面加个 ./my-sail.sh
就行,非常简单,应该说比官方的实现容易得多。
管理容器
进入容器
./my-sail.sh enter
重启容器
./my-sail.sh restart
停止容器
./my-sail.sh stop
启动容器
./my-sail.sh start
感兴趣的朋友可以自己定制my-sail.sh
文件,可以提升自己的 Linux 基础水平。
好了,教程到此结束!有任何困难欢迎评论区留言。
本作品采用《CC 协议》,转载必须注明作者和本文链接
希望楼主出一篇使用 docker 部署 laravel 项目到服务器的文章
这个多项目要怎么搞呢
laravel sail 适用于生产环境么,通常生产服务器都是直接部署的环境,而且很多旧项目的laravel版本比较老,不能用laravel sail,本地的开发环境管理起来也比较混乱
这些$命令都在Ubuntu中操作???有很多疑问?
问题一:按教程composer create-project laravel/laravel Example –prefer-dist “8.*”创建的项目少了vendor文件夹,两台电脑装了两次,都这样,在浏览器访问localhost提示没有’/../vendor/autoload.php’?不知道是网络原因,还是系统问题,还是安装过程?
详细:第一次按照laravel文档装在win10的C盘,有vendor;后来参照迁移教程重新安装一遍,就出现了问题一所述情况!查询搜索后出现vendor文件夹,解决过程如下:
问题二:对于问题一的解决是否正确,是否需要增改,原因不理解?
问题三:$ php artisan sail:install –with=mysql,redis这个命令是在ubuntu中安装mysql,redis?
问题四:发布 Dockerfile 以便定制,这节和之后都是在Ubuntu中执行?
问题五:容器已有,win10中还需要安装MySQL、composer?