发布于 2026-01-06 2 阅读
0

使用 NGINX 和 MySQL 在 Docker 上部署 Laravel 应用

使用 NGINX 和 MySQL 在 Docker 上部署 Laravel 应用

原文也上传到了这里:Laravel Application on Docker

如果您是 Django 开发人员,可以在这里找到一个非常全面的教程:Django on Docker

现在我们开始吧?

Docker,这位新来的“金靴”让所有人都兴奋不已。为什么?因为 Docker 能确保开发和生产周期的一致性,从而标准化你的环境,让开发变得无比轻松。

我猜你和我们一样对 Docker 充满热情,所以才会看到这篇文章。说实话,Docker 一开始确实很让人头疼,就像其他任何新概念一样,对新手来说都是噩梦。但一旦你掌握了它,就能节省大量部署时间。

这篇文章主要面向对 Docker 几乎一无所知的初学者。撰写这篇文章的初衷是,我在网上找不到任何全面的 Laravel Docker 教程。最终,我只能通过持续阅读多篇博客文章,并将所有内容整合起来,整理成一个庞大而全面的步骤,我将在本文中尝试记录这些步骤。

现在进入正题……

在开始之前,我假设您已经准备好了 Laravel 应用。如果您还没有,可以前往Laravel 文档页面创建一个应用,然后再回到这里继续阅读。

我还假设您的机器上已经安装了 Docker。如果没有,您可以选择以下方法:

  1. Windows 10 专业版用户:Docker Desktop
  2. Windows 10 专业版以下的 Windows 10 版本用户:Docker Toolbox。这是因为 Docker Desktop 对系统有一定要求。Docker Toolbox 利用了 VirtualBox 的功能。
  3. Linux 用户:Docker CentOS。您可以从弹出屏幕的侧边菜单中选择您的 Linux 发行版(如果不是 CentOS),然后按照该发行版的特定说明进行操作。

第一步:创建你的“docker-compose”文件

什么是 docker-compose 文件?这是一个定义所有 Docker 容器的文件,所有这些容器都可以通过运行一个相对简单的命令来启动,例如:

docker-compose -f docker-compose.prod.yml up --build
Enter fullscreen mode Exit fullscreen mode

在这里,我们将搭建一个开发环境(稍作修改后,也可以用于生产环境,我将在下一篇文章中记录这些修改 :-))

在根目录下创建一个文件,并将其命名为:docker-compose.yml

接下来,您将在本文件的步骤中定义容器。

在我们的 docker-compose 文件中,我们定义了三个容器:mysql、nginx 和我们的 laravel 应用程序。

首先,我们的 Laravel 应用容器将定义如下:

version: '2'

services:

  #  The Application
  app:
    container_name: laravel_app
    build:
      context: ./
      dockerfile: development/app.dockerfile
    volumes:
      - ./storage:/var/www/storage
    env_file: '.env.prod'
    environment:
      - "DB_HOST=database"
      - "REDIS_HOST=cache"
Enter fullscreen mode Exit fullscreen mode

以上代码概述:

  1. 版本- 您可以随意更改此版本
  2. container_name - 您将使用此名称来引用您的容器。例如,如果您想关闭容器,您将使用此名称来专门引用它。您也可以根据需要随意更改此名称。
  3. build - 用于从 Dockerfile 构建镜像。具有以下附加选项:

    • 上下文- Docker 使用此上下文(基本上就是 Laravel 文件所在的位置)来引用其中的任何文件。在本例中,`./` 指的是 Laravel 的根文件夹,假设 docker-compose 文件存储在 Laravel 的根文件夹中。
    • Dockerfile:Docker 镜像由 Dockerfile 构建,Dockerfile 通常包含在容器内运行的附加命令。在本例中,我们使用 Dockerfile 来构建应用程序容器。另请注意,我们使用了 `<path> development/app.dockerfile` 标签。这意味着我们的 Dockerfile 位于 Laravel 应用程序根目录下的 `development` 文件夹中。
  4. - Docker 容器使用卷在主机和正在运行的 Docker 容器之间共享文件。全冒号左侧代表主机,右侧代表 Docker 容器。在本例中,我们将 Laravel 应用存储文件夹中的所有数据共享给挂载在`/var/www/storage` 的Docker 容器。

  5. env_file - 这定义了我们的 Laravel 的 .env 文件,在本例中是 env.prod,我们将使用它来输入 Docker 容器特定的环境变量,我们将在本文后面看到。

  6. 环境变量- 这定义了将在我们的 Docker 容器上设置的环境变量。在本例中,如果我们可以在 Linux 容器内执行 bash 命令并引用此处定义的环境变量,例如,echo $DB_HOST将会输出:数据库

我们的 NGINX 容器定义如下:

# The Web Server
  web:
    container_name: nginx_server
    build:
      context: ./
      dockerfile: development/web.dockerfile
    volumes:
      - ./storage/logs/:/var/log/nginx
    ports:
      - 8990:80
Enter fullscreen mode Exit fullscreen mode

以上代码概述:

  1. container_name - 容器的名称,您可以选择更改它。
  2. 构建- 定义与上述相同。这里可以看到,我们将此容器的 Dockerfile 定义为 web.dockerfile。
  3. volumes - 定义同上。这里我们将 Laravel 的日志文件夹与 Nginx 的日志文件夹共享。
  4. 端口- 在这里,我们定义 Docker 容器将监听的主机端口以及 Docker 在容器部署期间创建的虚拟网络上的端口。这很容易理解:冒号左侧定义主机,因此定义主机上的端口;冒号右侧定义 Docker 容器,因此定义 Docker 容器上的端口。

我们的 MySQL 容器将定义如下:

# The Database
  database:
    container_name: mysql_database
    image: mysql:5.7
    volumes:
      - dbdata:/var/lib/mysql
    environment:
      - "MYSQL_DATABASE=Baly"
      - "MYSQL_USER=phpmyadmin"
      - "MYSQL_PASSWORD=phpmyadmin"
      - "MYSQL_ROOT_PASSWORD=finallyJDBC2017."
    ports:
      - 8991:3306
Enter fullscreen mode Exit fullscreen mode

以上代码概述:

  1. container_name - 请参考上文。
  2. 镜像- 在这种情况下,我们没有定义用于构建容器的 Dockerfile,而是定义了一个镜像。因此,我们的 Docker 容器将基于我们在此处定义的镜像构建mysql5:7。您可以将此 MySQL 版本替换为您正在开发的版本。请记住,对于您的 Laravel 应用程序,最新版本的 MySQL 可能无法正常工作。这是因为最新版本的 MySQL 使用了不同的身份验证技术,而这种技术可能不被 MySQL 或 PDO PHP 扩展所支持。因此,在使用 `.`mysql:latest而不是 `.`时,请务必小心mysql:5.7
  3. - 概念仍然相同,只是现在我们已经dbdata从主机定义了它将映射到/var/lib/mysqlDocker 容器。
  4. 环境- 与上述概念相同,不同之处在于,在这种情况下,我们的 MySQL 数据库将使用我们设置的变量进行初始化。因此,构建完成后,我们的容器将自动拥有一个名为 `<database_name>` 的数据库、一个名为`<user_name>`database的用户(密码为 `<password>`)以及一个 root 用户(密码为 `<rootpassword>` )。您可以根据需要随意更改这些设置。我们在配置文件中定义这些设置,以避免当前配置文件设置与容器配置文件设置冲突。secretsecretsecret_rootenv.prod.env
  5. 端口- 与上面相同,只是我们的 mysql 容器将在主机上的 8991 端口和容器网络上的 3306 端口(mysql 的默认端口)上监听。

定义您的命名卷

将以下内容复制粘贴到您的 docker-compose.yml 文件中:

volumes:
  dbdata:

Enter fullscreen mode Exit fullscreen mode

请确保保留 docker-compose.yml 文件中的缩进,以确保 docker-compose 能够正确读取。最终,您的 docker-compose 文件应如下所示:

version: '2'

services:

  #  The Application
  app:
    container_name: laravel_app
    build:
      context: ./
      dockerfile: development/app.dockerfile
    volumes:
      - ./storage:/var/www/storage
    env_file: '.env.prod'
    environment:
      - "DB_HOST=database"
      - "REDIS_HOST=cache"

  # The Web Server
  web:
    container_name: nginx_server
    build:
      context: ./
      dockerfile: development/web.dockerfile
    volumes:
      - ./storage/logs/:/var/log/nginx
    ports:
      - 8990:80

  # The Database
  database:
    container_name: mysql_database
    image: mysql:5.7
    volumes:
      - dbdata:/var/lib/mysql
    environment:
      - "MYSQL_DATABASE=Baly"
      - "MYSQL_USER=phpmyadmin"
      - "MYSQL_PASSWORD=phpmyadmin"
      - "MYSQL_ROOT_PASSWORD=finallyJDBC2017."
    ports:
      - 8991:3306

    # redis
  cache:
    image: redis:3.0-alpine

volumes:
  dbdata:

Enter fullscreen mode Exit fullscreen mode

第二步:定义我们的 Dockerfile。

在这一步中,我们将为刚刚在 docker-compose 文件中定义的容器定义 Dockerfile。这些 Dockerfile 将代表一系列我们希望在 Docker 容器内运行的命令。

定义我们的“app”Dockerfile(laravel_app)

在 Laravel 应用的根目录下创建一个名为 `.laravel` 的文件夹development。在该文件夹内,创建一个名为 `.laravel.js` 的文件app.dockerfile(注意,不要有任何文件扩展名)。打开该文件,并将以下代码复制粘贴到其中:

FROM php:7.2-fpm

COPY composer.lock composer.json /var/www/

COPY database /var/www/database

WORKDIR /var/www

RUN apt-get update && apt-get -y install git && apt-get -y install zip

RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" \
    && php -r "if (hash_file('SHA384', 'composer-setup.php') === 'a5c698ffe4b8e849a443b120cd5ba38043260d5c4023dbf93e1558871f1f07f58274fc6f4c93bcfd858c6bd0775cd8d1') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;" \
    && php composer-setup.php \
    && php -r "unlink('composer-setup.php');" \
    && php composer.phar install --no-dev --no-scripts \
    && rm composer.phar

COPY . /var/www

RUN chown -R www-data:www-data \
        /var/www/storage \
        /var/www/bootstrap/cache

RUN  apt-get install -y libmcrypt-dev \
        libmagickwand-dev --no-install-recommends \
        && pecl install mcrypt-1.0.2 \
        && docker-php-ext-install pdo_mysql \
        && docker-php-ext-enable mcrypt

RUN mv .env.prod .env

RUN php artisan optimize
Enter fullscreen mode Exit fullscreen mode

上述代码概述

  1. 从 php:7.2-fpm 开始——这意味着我们将从镜像构建容器php:7.2-fpm。此外,您可以根据您的开发环境需求更改此版本。

  2. 复制- 第一个复制命令将主机根目录下的文件复制composer.lockcomposer.jsonDocker/var/www/容器中。第二个复制命令将database主机上的文件夹复制到/var/www/databaseDocker 容器中的文件夹。这样做的原因有二:一是确保我们在开发环境(composer.json 文件)中使用的依赖项在下载依赖项时能够反映到容器中;二是确保在需要运行迁移migrate命令时,我们可以访问 Docker 容器内的迁移文件。

  3. WORKDIR - 我们设置了工作目录,这意味着在需要运行 bash 命令的情况下,/var/www我们不必进入此文件夹(移动到此​​文件夹)。cd

  4. 运行- 在这里,我们将安装 Laravel 所需的所有依赖项,包括 Composer 及其依赖项。请注意这一行。其中定义的哈希值会随着每次更新而改变,因此,如果您的安装程序失败并显示“安装程序已损坏”的if(hash_file('SHA384'...消息,请考虑从“获取哈希值”获取正确的哈希值

  5. COPY . /var/www - 此时,我们将所有文件夹内容复制到/var/wwwdocker 容器中的文件夹中。

  6. 运行- 在最后的运行命令中,我们会清除应用程序缓存和其他缓存,并安装 Laravel 用于连接数据库的 MySQL 驱动程序。之后,我们将.env.prod文件重命名,.env因为该文件将包含 Docker 容器环境特有的正确环境变量,因此 Laravel 应该使用它。我们运行命令php artisan optimize来删除该文件的缓存版本.env

请注意,无需复制根文件夹(例如 vendor 文件夹)中的所有内容,Docker 提供了一个.dockerignore功能与 dockeringore 文件非常相似的文件.gitignore。我们的 dockeringore 文件内容如下:

.git
.idea
.env
node_modules
vendor
storage/framework/cache/**
storage/framework/sessions/**
storage/framework/views/**
development
Enter fullscreen mode Exit fullscreen mode

将此文件保存在与您的 app.dockerfile 相同的文件夹中(开发文件夹)。

.env.prod复制粘贴您的.env文件并将其重命名为.env.prod。在数据库设置中,将 更改为与您的MySQLDB_HOST容器名称匹配,并将密码更改为与您在文件中定义的密码匹配。如果您按照我的所有步骤操作且未做任何更改,那么您的 .env.prod 文件应该类似于以下内容:docker-compose.yml

DB_CONNECTION=mysql
DB_HOST=mysql_database
DB_PORT=3306
DB_DATABASE=Baly
DB_USERNAME=phpmyadmin
DB_PASSWORD=phpmyadmin
Enter fullscreen mode Exit fullscreen mode

定义我们的“web”Dockerfile

在您刚刚创建的文件夹(开发文件夹)中,创建一个 Dockerfile 文件web.dockerfile。将以下内容复制粘贴到 Dockerfile 中:

FROM nginx:1.10-alpine

ADD development/vhost.conf /etc/nginx/conf.d/default.conf

COPY public /var/www/public

Enter fullscreen mode Exit fullscreen mode

上述代码概述

我们从镜像构建 Dockerfile:。nginx:1.10-alpine然后我们将 nginx 的default.conf文件替换为vhost.conf我们稍后将创建的文件。

我们还将 Laravel 应用的公共目录复制到 Nginx 的公共目录中,Nginx 将为我们所有的公共资源提供服务。

在同一目录(开发目录)下创建 vhost.conf 文件,并将以下内容复制粘贴到该文件中:

server {
    listen 80;
    index index.php index.html;
    root /var/www/public;
    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log;
    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;
    }
}

Enter fullscreen mode Exit fullscreen mode

我们的php-fpm容器将监听9000端口,因此app:9000

快到了……

所以,为了进行复核,您需要事先准备好以下文件:

  1. 根文件夹-docker-compose.yml.env.prod
  2. 开发文件夹
    • .dockerignore
    • app.dockerfile
    • web.dockerfile
    • vhost.conf

如果是这样,那么你就快完成了,但首先,还有一些前提条件:

如果您在 Windows 上使用 Docker Toolbox,并且您的 Laravel 应用文件夹位于除 `/etc/docker-compose up` 目录之外的其他文件夹中,C:/users则在主机和 Docker 容器之间共享卷时会遇到问题。这是因为当 Docker 虚拟机启动时,VirtualBox 不会挂载任何非 `/etc/docker-compose up` 目录的文件夹C:/users。因此,要解决此问题,请先运行以下命令停止正在运行的 Docker 虚拟机:

docker-machine stop
Enter fullscreen mode Exit fullscreen mode

然后打开 VirtualBox,右键单击名为“default”的虚拟机,然后单击“设置”。导航到“共享文件夹”并单击它,然后添加一个新文件夹,用于存放 Laravel 应用文件夹。记得勾选“自动挂载”。之后,运行以下命令启动 Docker 虚拟机:

docker-machine start default
Enter fullscreen mode Exit fullscreen mode

鼓声响起……

假设您已正确完成所有操作,请继续运行以下命令:

docker-compose up -d --build database && docker-compose up -d --build app && docker-compose up -d --build web 

Enter fullscreen mode Exit fullscreen mode

最后,执行以下命令进入 laravel_app 的 Docker 容器:

docker exec -it laravel_app bash
Enter fullscreen mode Exit fullscreen mode

然后执行以下 Laravel 命令:

php artisan key:generate

php artisan config:cache

php artisan route:cache

Enter fullscreen mode Exit fullscreen mode

请确保在 Laravel 应用的根目录下运行此命令。此命令会构建容器镜像并最终启动它们。如果一切顺利,您应该能够通过以下地址访问在容器中运行的 Laravel 应用:

0.0.0.0:8990
Enter fullscreen mode Exit fullscreen mode

如果您使用了不同的端口,请将其替换8990为您在 docker-compose.yml 文件中定义的端口。

另外请注意,对于使用 Docker Toolbox 的用户,Docker 会创建一个虚拟网络并为其分配一个 IP 地址。您可以通过搜索docker quickstart terminal并运行命令来找到此 IP 地址。分配的 IP 地址将显示在弹出的终端窗口中,您可以通过以下方式访问您的 Laravel 应用:

your-docker-machine-ip:8990
Enter fullscreen mode Exit fullscreen mode

好了,各位!你们已经成功将 Laravel 应用部署到 Docker 上了!敬请期待我的下一篇文章,我将在其中介绍如何将 Laravel 应用部署到生产环境。

文章来源:https://dev.to/balachbryan/deploying-your-laravel-app-on-docker-with-nginx-and-mysql-56ni