拥抱 Docker!Laravel 老项目开发环境从 Homestead 迁移到 Sail
前言
作为程序员,一直以来的开发环境都是在虚拟机下。既可以标准化、又方便迁移,还有一点是不会弄脏弄乱原生系统。特别是用 Laravel 框架的时候,Homestead + Vagrant + VirtualBox 非常好用,一个 vagrant up
命令把所有依赖都装好,开箱即用。让我们把时间和精力都放在开发上。
不过用的时间长了,Homestead 也是有一定的弊端的。比如启动时间长、吃硬盘、耗资源,当时就想着能不能用 Docker 替代虚拟机。早期的时候 Laravel 官方还没有基于 Docker 的解决方案,不过有一些第三方的,怕不靠谱就懒得折腾了。而且 Homestead 本身确实比较优秀,用起来还是比较方便的,就一直拖下来了。现在官方出了 Sail,正好把之前几个项目都转到 Sail 环境下,把我的 MBP 的资源都释放出来。
网上很多类似迁移教程都是针对新项目的。本篇文章记录的是老项目从 Homestead 迁移到 Sail。老项目比新项目要复杂一些,如果你正好有这方面需求,希望这篇文章能够帮助到你。
我在迁移不同的项目过程中都会踩到不同的坑,解决方案我会补充在文章里。如果你碰到了问题,仔细看看文章里面有没有解决方案。如果没有,欢迎给我留言。
1. 安装 Docker
这个就不说了,很简单,网上教程一大堆。
2. 关闭 .env 里面的 redis 和 memcached 配置
FILESYSTEM_DRIVER=public
BROADCAST_DRIVER=log
CACHE_DRIVER=redis
QUEUE_CONNECTION=redis
SESSION_DRIVER=memcached
SESSION_LIFETIME=120
改为:
FILESYSTEM_DRIVER=public
BROADCAST_DRIVER=log
CACHE_DRIVER=file
QUEUE_CONNECTION=sync
SESSION_DRIVER=file
SESSION_LIFETIME=120
不关闭 redis 配置的话,后面执行 composer 命令的时候会因为没有 redis 服务而报错。
3. 安装 Sail
$ cd ./project
$ docker run --rm \
-u "$(id -u):$(id -g)" \
-v $(pwd):/var/www/html \
-w /var/www/html \
laravelsail/php81-composer:latest \
composer require laravel/sail --dev
离开了 Homestead 环境,我们假设原生系统下没有安装 php 和 composer「至少我的是这样」。所以要通过 composer 去安装 Sail 就成了难题了。难不成为了装 Sail 再装一套 php + composer?那就与 Docker 精神背道而驰了。细心的 Laravel 团队肯定也想到了这一点,所以提供了一个只有 php + composer 的小容器 laravelsail/phpXX-composer
给我们来安装 Sail。
这个 phpXX 是该项目下对应的 php 版本,比如 74、80、81。例子里我们就用 81 来演示。
当然,你可以在以前的 Homestead 环境下执行 composer require laravel/sail --dev
,完全没有问题,效果是一样的。
如果在执行命令的时候有什么组件因为 php 扩展的问题报错,可以先在 composer.json
里把报错的组件删掉,等 Sail 搭好了再重新安装。因为毕竟这是一个简化版的镜像,不会象 Sail 开发环境那样启用很多扩展,它的目的只是安装 Sail。
4. 生成 docker-compose.yml
$ docker run --rm \
-u "$(id -u):$(id -g)" \
-v $(pwd):/var/www/html \
-w /var/www/html \
laravelsail/php81-composer:latest \
php artisan sail:install --with=mysql,redis,memcached
上一步已经把 Sail 安装好了,现在就是要生成 docker-compose.yml 编排文件。--with
后面跟的是这个项目下面需要的组件。支持的有:
mysql
pgsql
mariadb
redis
memcached
meilisearch
minio
selenium
mailhog
只要把需要的组件加在 with 后面,就会自动编排到配置文件里面。演示中我添加了 mysql
,redis
和 memcached
。
如果用到了VSCode
的Remote - Containers
来管理开发环境,可以在--with=XXX
后面加上--devcontainer
,这样还会额外生成 VSCode 需要的devcontainer.json
文件。
完成这步操作以后就可以恢复 .env 里的 redis 和 memcached 了。
其实到这一步 Sail 就算安装好了,可以运行 ./vendor/bin/sail up
。后面的操作是一些优化步骤。
5. 修改 Dockerfile
$ cp -r ./vendor/laravel/sail/runtimes ./docker
因为一些众所周知的原因,我们需要对 Dockerfile 进行一些修改和优化,而 Dockerfile
文件原本在 ./vendor/laravel/sail/runtimes/X.X
下面「又是 XX」。Laravel 的约定是不能直接修改 ./vendor/
下的任何文件,因为一更新就没啦,所以我们需要把它复制出来。
把 ./vendor/laravel/sail/runtimes
整个文件夹复制一份放在项目根目录下,文件夹名字改为 docker
。docker
下面有 7.4
、8.0
、8.1
三个子文件夹,里面的文件都一样,用哪个版本的 php 就修改相应文件夹下面的文件。咱们还是用 8.1
来演示。
Dockerfile 用来创建一个容器
docker-compose.yml 用来创建一堆容器,并且按照一定的网络和依赖关系组合起来
$ vim ./docker/8.1/Dockerfile
FROM ubuntu:22.04
LABEL maintainer="Taylor Otwell"
ARG WWWGROUP
ARG NODE_VERSION=16
ARG POSTGRES_VERSION=14
WORKDIR /var/www/html
ENV DEBIAN_FRONTEND noninteractive
ENV TZ=UTC
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
RUN apt-get update \
.
.
.
改为:
FROM ubuntu:20.04
LABEL maintainer="Taylor Otwell"
ARG WWWGROUP
ARG NODE_VERSION=16
ARG POSTGRES_VERSION=14
WORKDIR /var/www/html
ENV DEBIAN_FRONTEND noninteractive
ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
ADD sources.list /etc/apt/
RUN apt-get update \
.
.
.
FROM ubuntu:22.04
=>FROM ubuntu:20.04
我比较习惯 20.04,这个改不改随个人喜好。改成 20.04 以后,该文件中的jammy
全部要改成focal
。ENV TZ=UTC
=>ENV TZ=Asia/Shanghai
我是中国人🇨🇳ADD sources.list /etc/apt/
给容器启动的时候添加国内镜像源
6. 设置镜像源
$ vim ./docker/8.1/sources.list
# 默认注释了源码仓库,如有需要可自行取消注释
deb http://mirrors.ustc.edu.cn/ubuntu/ focal main restricted universe multiverse
# deb-src http://mirrors.ustc.edu.cn/ubuntu/ focal main restricted universe multiverse
deb http://mirrors.ustc.edu.cn/ubuntu/ focal-security main restricted universe multiverse
# deb-src http://mirrors.ustc.edu.cn/ubuntu/ focal-security main restricted universe multiverse
deb http://mirrors.ustc.edu.cn/ubuntu/ focal-updates main restricted universe multiverse
# deb-src http://mirrors.ustc.edu.cn/ubuntu/ focal-updates main restricted universe multiverse
deb http://mirrors.ustc.edu.cn/ubuntu/ focal-backports main restricted universe multiverse
# deb-src http://mirrors.ustc.edu.cn/ubuntu/ focal-backports main restricted universe multiverse
# 预发布软件源,不建议启用
# deb http://mirrors.ustc.edu.cn/ubuntu/ focal-proposed main restricted universe multiverse
# deb-src http://mirrors.ustc.edu.cn/ubuntu/ focal-proposed main restricted universe multiverse
几点说明:
- 这里我用了中科大的源,用什么源也是个人喜好,只不过我一开始用阿里云的源的时候一直超时,换中科大的就没问题。
不管什么源,只能用
http
,不能用https
,会报下面的错误:Certificate verification failed: The certificate is NOT trusted. The certificate issuer is unknown. Could not handshake: Error in the certificate verification.
- 重复一遍,
20.04
为focal
,22.04
为jammy
7. 修改 docker-compose.yml
$ vim ./docker-compose.yml
# For more information: https://laravel.com/docs/sail
version: '3'
services:
laravel.test:
build:
context: ./vendor/laravel/sail/runtimes/8.1
.
.
.
改为:
# For more information: https://laravel.com/docs/sail
version: '3'
services:
laravel.test:
build:
context: ./docker/8.1
.
.
.
前面选了 8.1
,这里就写 8.1
8. 启航!
$ ./vendor/bin/sail up
后记
第一次 sail up
生成镜像的时候还是挺耗时的,需要耐心等待一段时间。这个时候网络环境特别重要,这就是为什么要那么费劲添加国内镜像源了。
如果卡在下面这个地方一直不动:
#0 192.1 gpg: keybox '/root/.gnupg/pubring.kbx' created
解决步骤:
- 打开第 5 步里的
Dockerfile
- 找到
hkp://keyserver.ubuntu.com:80
- 改为
hkp://keyserver.ubuntu.com