Laravel + Docker 第 1 部分-开发设置
本文共计两个部分,这是第一部分。我们将介绍如何使用 Docker 在本地运行Laravel 应用程序。 然后第 2 部分将展示如何在生产环境中运行相同的应用程序来完成本教程。
第一篇文章的目标是创建一个可复制的开发环境,该环境轻巧,快速并且不依赖于本地计算机上全局安装的任何内容(docker 本身除外)。
所以,我们将实现以下目标。
- 不需要 Mamp 或者其他类似的程序
- 不需要 Vagrant 或者其他类似的虚拟机
- 不需要 全局安装的 PHP
- 不需要 全局安装的 Composer
第1步 — 获取最新版的 Laravel
我将通过 curl 的方式来获取 github 上最新的 Laravel 代码,这样可以对获取的代码进行多份复制 — 你可以通过执行git clone
来获取 — 但是不要忘记在完成后清理 .git 文件。
这里我们不遵循 Laravel 官方指南的设置,因为我们不希望在机器上安装全局的 PHP/Composer。
curl -L <https://github.com/laravel/laravel/archive/v5.3.16.tar.gz> | tar xz
执行上面的命令将得到一个名为 laravel-5.3.16 的目录 —你应将其命名为你想要的项目名称。例如 mv laravel-5.3.16 my-site
(重命名为 my-site)然后 cd
进入目录。
步骤2 — 安装依赖
我们需要运行 composer install
来提取所有组成 Laravel 的库-我们可以使用来自[docker hub]的 composer docker hub 为我们处理此问题。
我们将通过执行以下命令来创建一个一次性容器。
docker run --rm -v $(pwd):/app composer/composer install
注意:
- 我们使用
--rm
标志确保此容器不会在安装后逗留。 -v $(pwd):/app
用于将主机(您的cpu)上的当前目录挂载到容器中的 /app 中 —这是在 Composer 内部运行的位置容器希望找到一个 composer.json-v $(pwd):/app
还将确保由 composer 在容器内创建的vendor
文件夹在我们的计算机上也可见。
步骤 3 — 创建开发文件 docker-compose.yml
我们将使用2个单独的文件来定义环境的运行方式。一个用于开发,另一个用于生产。现在,Docker-compose
确实支持使用多个输入文件,允许您覆盖特定的键-但由于它合并数组的方式,因此不适用于我们的特定用例。我们只需要忍受两个文件中的重复项即可。
无论如何,您需要创建以下文件:
docker-compose.yml
它应该开始于……
version: '2'
services:
... our services will go here
…我们可以开始在其中添加服务。
PHP-FPM
这用于在应用程序内处理代码的执行。我们还将使用它执行任意php脚本-例如运行Laravel附带的 artisan CLI 工具。 (请记住,这部分配置位于上方的「 service 」键下- 莫慌,后面会有完整的代码片段)
app:
build:
context: ./
dockerfile: app.dockerfile
working_dir: /var/www
volumes:
- ./:/var/www
environment:
- "DB_PORT=3306"
- "DB_HOST=database"
view rawdocker-compose.yml hosted with ❤ by GitHub
注意:
- 我们将使用单独的 app.dockerfile *(line ** 4 )* 来构建我们的镜像,因为我们想精确地控制PHP使用的扩展模块。
- 我们将工作目录设置为 /var/www,这是应用代码位于容器内的位置,因此,如果我们将 CD 附加到容器上,则可以避免将 CD 放入该文件夹中。它还将使
exec
命令更短(我们将很快看到一个示例) - 我们使用单个的数据卷定义
./:/var/www
将主机当前目录中的所有内容挂载到容器中的/var/www
目录中。这将使我们能够对源代码进行更改,并将其立即体现在正在运行的应用程序中。这会使您的应用在浏览器中有延迟-滞后几百毫秒(尤其是在 OSX 上),但不要担心-在第2部分中,当我们过渡到生产设置时,速度问题将不再存在。
host:容器卷映射说明
- 在此处设置环境变量
DB_PORT
和DB_HOST
以匹配我们稍后创建的数据库容器
现在我们需要创建我们在上面的 build
设置中引用的 app.dockerfile
。
FROM php:7.0.4-fpm
RUN apt-get update && apt-get install -y libmcrypt-dev \
mysql-client libmagickwand-dev --no-install-recommends \
&& pecl install imagick \
&& docker-php-ext-enable imagick \
&& docker-php-ext-install mcrypt pdo_mysql
注意:
- 在这里使用
php:7.0.4-fpm
,你可以选择任何 PHP 版本。 - 剩下的就是典型的 Laravel CRUD 应用程序所需要的基本依赖,并且额外添加了 imagick 依赖(我有一些应用需要图片处理 :))
NGINX
接下来,我们需要配置一个 Web 服务器,用来处理静态文件以及将请求传递给 Laravel 应用程序处理。我们将遵循与以前相同的模式,这次将服务命名为 web
及其附带文件web.dockerfile
web:
build:
context: ./
dockerfile: web.dockerfile
working_dir: /var/www
volumes_from:
- app
ports:
- 8080:80
注意:
- 我们在这里使用
volumes_from
复用我们在上面的PHP-FPM服务中定义的内容。这意味着该 nginx 容器将继承/var/www
目录(该目录又挂载到我们的开发机上) - 我们将主机上的端口 8080 映射到容器中的 80 。这样一来,我们就可以访问正在开发中的
0.0.0.0:8080
,而无需弄混主机名了。
接下来,我们将创建上述的 web.dockerfile :
FROM nginx:1.10
ADD vhost.conf /etc/nginx/conf.d/default.conf
注意:
- 如您所见,这只是标准的Nginx官方映像,并添加了我们本地目录中的 vhost.conf 文件(接下来创建)来配置服务器。
这是 vhost.conf 文件
server {
listen 80;
index index.php index.html;
root /var/www/public;
location / {
try_files $uri /index.php?$args;
}
location ~ \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass app:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
}
}
注意:
- 请注意*** 12 *上我们是如何将php请求移交给
app:9000
-这是可行的,因为docker-compose
会自动链接我们的服务,使它们能够通过这些简单的主机名彼此 talk (通信)。 - 剩下的只是非常基本的 nginx 配置-并未针对性能或安全性进行任何调整-我们将在另一篇文章中处理!
MYSQL
接下来,我们将配置数据库,但是我们需要处理该数据库的方式与以前的服务略有不同。借助 PHP-FPM 和 Nginx,我们希望可以从容器内部访问 主机 目录中的文件,以帮助加快开发过程。但这不适用于数据库-相反,我们希望容器中创建的文件能够持久保存,从而使我们能够停止和重新启动服务而不会丢失数据。可以通过卷来实现,只是这一次不需要将其与我们的主机文件同步。
version: '2'
services:
database:
image: mysql:5.6
volumes:
- dbdata:/var/lib/mysql
environment:
- "MYSQL_DATABASE=homestead"
- "MYSQL_USER=homestead"
- "MYSQL_PASSWORD=secret"
- "MYSQL_ROOT_PASSWORD=secret"
ports:
- "33061:3306"
volumes:
dbdata:
注意:
-
在 16 行我们创建一个名为 dbdata 的卷(后面的
:
是必须的,yaml的限制,你不必在意) -
然后,在 7 行上,我们使用
<name>:<dir>
格式引用该卷,这就是「说从名为 dbdata 的卷中挂载目录/var/lib/mysql
」 -
我们在第9、10、11和12行设置了 MySql docker 镜像所需的环境变量。
-
我们使用 homestead 作为数据库/用户名,并使用 secret 作为密码,因为这些值与Laravel自带的
.env
配置文件中的默认值相匹配,这意味着我们不用再修改.env
文件了。 -
最后,在第13行,我们在主机上创建一个 33061 的端口映射到容器内的常规端口 3306。这样做仅仅是为了在开发过程中允许外部工具更容易地访问数据库-在生产设置中将不需要它。
所有服务
现在让我们看一下最终的 docker-compose.yml
,以了解这些组件是如何组合在一起的。
version: '2'
services:
# The Application
app:
build:
context: ./
dockerfile: app.dockerfile
working_dir: /var/www
volumes:
- ./:/var/www
environment:
- "DB_PORT=3306"
- "DB_HOST=database"
# The Web Server
web:
build:
context: ./
dockerfile: web.dockerfile
working_dir: /var/www
volumes_from:
- app
ports:
- 8080:80
# The Database
database:
image: mysql:5.6
volumes:
- dbdata:/var/lib/mysql
environment:
- "MYSQL_DATABASE=homestead"
- "MYSQL_USER=homestead"
- "MYSQL_PASSWORD=secret"
- "MYSQL_ROOT_PASSWORD=secret"
ports:
- "33061:3306"
volumes:
dbdata:
启动服务
如果您一直跟着做,我们就快成功了!但是,在启动环境之前,我们需要确保1)您按照帖子中前面的说明运行了composer install&2
)在项目的根目录中创建了以下文件(以上均已详细介绍)。
- docker-compose.yml
- app.dockerfile
- web.dockerfile
- vhost.conf
这里的 gist 包含了所有的文件,为你引用、复制、粘贴所需
一旦所有这些都准备就绪,就可以继续执行以下命令,这将启动所有3个服务。
docker-compose up
注意:
- 首次运行此程序时,它需要几分钟的时间才能开始,因为它将需要下载所有3个服务的镜像。随后的开始时间将在1到2秒钟左右,所以不要被最初的下载时间所推迟。(译者注: 注意使用国内的镜像源或者提前下载好镜像 并
docker load -i XXX
导入 ,避免因为网络问题卡在这里)最后的步骤,准备 Laravel 应用程序。
接下来的还有几个操作需要处理,如果你的 Laravel 应用是使用的是官方安装程序创建的,这些操作已经自动处理了。
环境配置文件
我们首先需要将.env.example
文件复制到我们自己的 .env
文件中。该文件不会被纳入版本控制,我们将为开发和生产提供单独的文件。现在,只需复制 .env.example
-> .env
应用程序密钥和优化
接下来,我们需要设置应用程序密钥并运行优化命令。这两个都是由artisan
处理的,但是因为 PHP 和整个 Laravel 应用运行在容器内部,所以我们不能像您平时操作一样,只是在本地计算机上运行php artisan key:generate
-我们需要将这些命令发布到容器中。
幸运的是,docker-compose有一个非常好的抽象来处理此问题,所需的两个命令如下所示:
docker-compose exec app php artisan key:generate
docker-compose exec app php artisan optimize
直白的说,第一行的意思是:
在服务「app」使用的容器内执行命令
php artisan key:generate
为了清晰起见,以下图片展示了这些命令是如何分解的:
每当您想使用artisan
时,都将需要此模式-记住使用docker的全部目的是避免在本地计算机上安装 PHP 版本的麻烦,这就是我们的解决方法-通过将命令发送到容器中,而不是直接运行它们。
您将在 Laravel 项目中经常运行的其他一些命令:
docker-compose exec app php artisan migration --seed
docker-compose exec app php artisan make:controller MyController
我想您现在明白了。
小建议: 创建一个 alias 比如 phpd 这样不需要输入完整的命令, 例如:
phpd artisan migrate --seed
一旦您执行了前面提到的两个命令 (artisan key:generate
& artisan optimize
) 程序现在将准备使用 — 继续并点击http://0.0.0.0:8080 在你的浏览器中,你会看到这个可爱的屏幕。
妈妈,快看我的机器上没有安装PHP。
快乐开发吧!
下一步, 修改设置为 production.
现在已经有一些博客发布了关于Laravel像这样的开发环境, 但迄今为止我还没有发现一个如何完成以下重要步骤 — 使用此环境并使其准备好投入生产环境使用。我期待很快能和大家分享。
资源:
像这样吗?如果你这样做了,你会发现自己在做任何前端工作,也许你会喜欢我的一些课程https://egghead.io/instructors/shane-osbourne—很多都是免费的,包括Vanilla JS、Typescript、RxJS等。
本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。
好文章,讲的很清晰
换了国内镜像,已然没法成功,安装了一晚上 :sob:
建议在内容页面添加一栏英文原文,类似于双语阅读的那种。
这篇博客是2017年发布的,有些年头了,而且软件的迭代更新很快,难免有些过时。在这里总结一下实践过程中遇到的一些坑
注意在 daemon.json 中配置国内镜像地址,或者自己的镜像仓库
docker run --rm -v $(pwd):/app composer/composer install
镜像 composer/composer 已经弃用了, 改为 composer 了
修改镜像的 yum 源, 参考docker apt-get 换源问题 , 强烈建议使用第二种 拷贝sources.list 文件的方式, 第一种有坑我没解决
php 依赖安装,这里我用的是
FROM php:7.2-fpm
, 将 mysql-client 替换为 mariadb-client , mcrypt 7.1 的时候废弃了,7.2的时候移除了,所以在这 把 libmcrypt-dev 和 mcrypt 相关的都删掉, 或者简单起见直接去 hub.docker.io 上找个现成的dockerifle 替换掉, 仅供参考 dongshufeng/my-php或者 简单粗暴直接 用现成的 image
最后 跑起来了
如果想使用 docker-compse 部署的项目,最好稍微系统的看一下这块,要不然你会发现好多坑,然后就弃坑了
好了就这么多 -:)
提个小建议,如果把代码的行好也加上,然后在说修改多少行的时候的,能找得更精准了。
在本地安装docker for desktop, 然后用docker-composer安装,再也不担心污染本地环境了。想切换php 版本也太快了。