拥抱 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 后面,就会自动编排到配置文件里面。演示中我添加了 mysqlredismemcached

如果用到了 VSCodeRemote - 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 整个文件夹复制一份放在项目根目录下,文件夹名字改为 dockerdocker 下面有 7.48.08.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.04focal22.04jammy

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

解决步骤:

  1. 打开第 5 步里的 Dockerfile
  2. 找到 hkp://keyserver.ubuntu.com:80
  3. 改为 hkp://keyserver.ubuntu.com
本作品采用《CC 协议》,转载必须注明作者和本文链接
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 19
李铭昕

如果是 MBP

Docker 也是要跑在虚拟机里的

1年前 评论
huzhuolei (楼主) 1年前

阿里云镜像说由于Docker Hub限制,现在不推荐使用镜像了,不然会拉取不到最新的镜像。实测拉的都是半年前的。
中科大的受影响吗?

1年前 评论
李铭昕 1年前
tomcath (作者) 1年前
huzhuolei (楼主) 1年前
tomcath (作者) 1年前
huzhuolei (楼主) 1年前

本站教程中的Homestead ,我就没有部署成功。。现在还在继续用thinkphp5...

1年前 评论
huzhuolei (楼主) 1年前
mengdodo

sail一个项目一个运行时容器,安装好php环境的sail容器近1个G,如果有20个项目 (普通公司这个项目数不过分),不包含代码的情况下这就20个G的空间没了,如果不关闭当前不需要的项目容器,他们都在占用内存和CPU, 还是homestead适合多项目开发啊

1年前 评论
huzhuolei (楼主) 1年前
huzhuolei (楼主) 1年前
mengdodo (作者) 1年前

@mengdodo

file

这是我的一个 laravel sail 项目运行时的硬盘占用情况

1年前 评论
mengdodo 1年前
sreio

file

1年前 评论

后记解决了我的问题, 大佬怎么发现的解决办法, 真的太强了。

1年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!