在上一篇 Docker 学习笔记 - 在 Linux 上安装和使用 Docker 中,已经包括了 Docker 的安装,容器和镜像管理,文件拷贝,挂载目录和映射卷。

这里就使用上一篇笔记中掌握的内容来安装一个简单的 PHP 运行环境,PHP、Caddy、MySQL 我会使用单独的镜像,虽然也有集成了 PHP + MySQL + Web服务器的镜像,但是版本和配置都不太自由。

创建自定义 Docker 网络

因为 Caddy、PHP、MySQL 运行在不同的容器,这些程序之间需要通过 TCP 通信,如果使用 127.0.0.1,访问到的还是容器内部的本地网络,无法访问到其它容器的服务。

虽然可以使用宿主机的 IP,但是 IP 可能会变,一旦 IP 改变,配置文件也需要更改,甚至程序代码也需要更改,不太方便。

这里使用 Docker 的自定义网络,创建一个自定义网络,Caddy、PHP、MySQL 容器都可以加入同一个网络,加入网络后可以直接通过容器名称访问,宿主机 IP 改变也不会影响 Docker 网络。

创建自定义网络:

docker network create web-net

这个自定义网络的名称就是 web-net

安装 PHP

PHP 官方的 Docker 镜像配置比较麻烦,可能需要用到 Dockerfile,前面的笔记中还没有涉及到 Dockerfile 的内容,所以这里会用到第三方的 PHP 镜像,使用的还是 docker run + 选项的方式来运行。

我这里使用的镜像是 https://hub.docker.com/r/dockette/php

这里提供了从 PHP5.6 到 8.3 的镜像,镜像的 PHP 包含了 CLI、FPM、Composer 和常用扩展。

下面安装 7.4 的 PHP:

docker run -d --name php74-fpm --network web-net --restart unless-stopped -v /www:/srv dockette/php:7.4-fpm

下面是详细说明:

  • docker run: 运行一个容器,如果镜像不存在,Docker 会自动下载镜像。
  • -d: 在后台运行。
  • --name php74-fpm: 设置一个容器名称,这里设置的名称是 php74-fpm
  • --network web-net: 让这个容器加入上面创建的自定义网络,web-net 就是自定义网络的名称。
  • --restart unless-stopped: 设置容器启动策略,宿主机重启或容器崩溃时,可以自动启动,除非手动停止。
  • -v /www:/srv: 把宿主机的 /www 目录挂载到容器内的 /srv ,由于容器内的程序无法直接访问宿主机的目录和文件,所以需要通过挂载目录的方式让容器内的 PHP 访问宿主机的 PHP 文件。
  • dockette/php:7.4-fpm: 镜像名称。

这里没有单独配置端口映射,无法远程通过 9000 端口来访问 PHP-FPM,如果需要远程连接,或直接通过宿主机上的 Web 服务器连接,可以加入 -p 9000:9000

运行完成后可以输入:

docker ps

查看正在运行的容器。

也可以进入 PHP 容器内,查看 CLI:

docker exec -it php74-fpm bash

查看 PHP 版本:

php -v

退出 PHP 容器:

exit

安装 Caddy

这里使用 Caddy 官方的镜像 https://hub.docker.com/_/caddy

创建一个目录来存放 Caddy 配置:

mkdir -p /opt/caddy/conf

上面的 /opt/caddy/conf 目录也是 Caddy 官方推荐的,把 Caddyfile 放到这个目录,不建议直接挂载单个 Caddyfile 文件。

下面在 /opt/caddy/conf 目录放一个 Caddyfile 文件,文件内容如下:

# PHP 网站
http://:80 {
    # 网站目录
    root * /srv
    # 启用静态文件服务和目录显示
    file_server browse
    # 配置 caddy 和 PHP 的通信方式和路径
    php_fastcgi php74-fpm:9000
}

网站目录设置的是 /srv ,运行容器的时候会把宿主机的 /www 目录挂载到容器内的 /srv ,Caddy 访问 /srv 其实访问的就是宿主机的 /www

php_fastcgi 设置的是 php74-fpm:9000 ,运行 Caddy 容器的时候,我会把容器加入上面创建的自定义网络,因为 Caddy 容器和 PHP 容器在同一个网络,所以可以直接通过容器名称访问,PHP 容器的名称就是 php74-fpm

配置文件准备就绪后开始下载和运行 Caddy 镜像:

docker run -d --name caddy-dev -p 80:80 --network web-net --restart unless-stopped -v /www:/srv -v /opt/caddy/conf:/etc/caddy -v caddy_data:/data caddy:latest

下面是详细说明:

  • docker run: 运行容器,如果镜像不存在会尝试自动下载。
  • -d: 在后台运行。
  • --name caddy-dev: 把容器名称设置为 caddy-dev
  • -p 80:80: 把容器的 80 端口映射到宿主机的 80 端口,左边是宿主机端口,右边是容器内的端口。
  • --network web-net: 让容器加入上面创建的 web-net 自定义网络。
  • --restart unless-stopped: 设置容器启动策略,宿主机重启或容器崩溃时,可以自动启动,除非手动停止。
  • -v /www:/srv: 把宿主机的 /www 目录挂载到容器内的 /srv 目录,容器内的 Caddy 访问 /srv 目录,访问的就是宿主机的 /www 目录。
  • -v /opt/caddy/conf:/etc/caddy: 把宿主机的 /opt/caddy/conf 目录挂载到容器内的 /etc/caddy 目录,这是存放 Caddyfile 配置的目录。
  • -v caddy_data:/data: 映射数据卷,把 caddy_data 映射到容器内的 /data 目录,Caddy 会把 SSL 之类的文件放到这个目录。
  • caddy:latest: 镜像名称。

运行完成后可以输入:

docker ps

查看正在运行的容器。

如果你的系统或服务器有防火墙的话,需要先开放 80 端口。

上面设置的网站目录是 /www 目录,可以在 /www 目录创建一个 index.php 文件,添加:

<?php

phpinfo();

保存后在浏览器访问 IP,应该能看到类似下面的内容:

phpinfo信息截图

PHP 和服务器成功运行后安装 MySQL 就比较容易了。

安装 MySQL

我这里会使用官方的 MySQL 镜像 https://hub.docker.com/_/mysql

下面安装 MySQL5.7:

docker run -d --name mysql57 --network web-net -p 3306:3306 --restart unless-stopped -v mysql57_data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD="123456" mysql:5.7 --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci

下面是详细说明:

  • docker run: 运行容器,如果镜像不存在会自动下载镜像。
  • -d: 在后台运行。
  • --name mysql57: 把容器名称设置为 mysql57
  • --network web-net: 让 MySQL 容器加入上面创建的 web-net 网络。
  • -p 3306:3306: 把宿主机 3306 端口映射到容器 3306 端口。
  • --restart unless-stopped: 设置容器启动策略,宿主机重启或容器崩溃时,可以自动启动,除非手动停止。
  • -v mysql57_data:/var/lib/mysql: 映射数据卷,MySQL 会把数据库存储在 /var/lib/mysql
  • -e MYSQL_ROOT_PASSWORD="123456": 把 MySQL 的 root 密码设置为 123456
  • mysql:5.7: 镜像名称。
  • --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci: 设置字符编码为 utf8mb4。

成功运行后可以进入容器:

docker exec -it mysql57 bash

尝试连接 MySQL:

mysql -uroot -p

如果提示 Enter password 就输入 root 密码,成功连接后可以看到:

Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.7.44 MySQL Community Server (GPL)

Copyright (c) 2000, 2023, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MySQL 安装成功。

PHP 连接 MySQL

PHP 和 MySQL 运行在不同的 Docker 容器,不能直接使用 localhost127.0.0.1 连接。

上面创建了一个名为 web-net 的自定义 Docker 网络,Caddy、PHP、MySQL 容器都已经加入了这个网络,可以直接使用容器名称连接。

下面是一个使用 PDO 连接 MySQL 的示例:

<?php

const DATABASE_TYPE = 'mysql';  //  数据库类型
const DATABASE_SERVER = 'mysql57';  //  服务器地址,MySQL 容器的名称是 mysql57
const DATABASE_NAME = 'bbs';  //  要连接的数据库名称
const USER_NAME = 'root';  //  数据库用户名
const PASSWORD = '123456';  //  数据库密码
const DSN = DATABASE_TYPE . ':host=' . DATABASE_SERVER . ';dbname=' . DATABASE_NAME;

try {
    $pdo = new PDO(DSN, USER_NAME,PASSWORD);
}catch (PDOexception $e) {
    echo $e->getMessage();
}

phpMyAdmin 默认使用的也是 localhost ,需要更改 phpMyAdmin 配置才能连接到 MySQL。

打开 phpMyAdmin 的目录,找到 config.sample.inc.php ,更改内容:

$cfg['Servers'][$i]['host'] = 'mysql57';  // 默认是 localhost,需要改为容器名称

更改完成后把 config.sample.inc.php 重命名为 config.inc.php

上面安装 MySQL 的时候还单独映射了 3306 端口,如果在宿主机上运行程序来连接 MySQL 是可以使用 127.0.0.1 连接的,远程也可以使用 IP 连接。