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 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。
推荐文章: