利用docker-compose搭建LAMP+phpmyadmin环境

zhangxiaocc 2020-05-03

  本文主要阐述如何利用docker-compose搭建LAMP(Linux+Apache+MySQL+PHP)环境,实现web服务。

整体思路:利用Apache变体镜像apache:<version>-apache及MySQL搭建LAMP环境,同时使用phpmyadmin/phpmyadmin镜像实现web数据库管理。

apache:<version>-apache:该变体包含了Debian的Apache httpd和PHP;
  phpmyadmin/phpmyadmin:该镜像用于数据库的可视化操作,实现数据库的管理。

??一. docker-compose的安装

参考install docker-compose中docker-compose在linux上的安装,具体步骤:

  • 运行如下命令,下载当前稳定版本的docker-compose:

sudo curl -L "https://github.com/docker/compose/releases/download/1.25.5/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
利用docker-compose搭建LAMP+phpmyadmin环境

  • 运行命令sudo chmod +x /usr/local/bin/docker-compose为docker-compose添加可执行权限:
    利用docker-compose搭建LAMP+phpmyadmin环境
  • 运行命令docker-compose --version,出现版本信息,说明docker-compose安装成功:
    利用docker-compose搭建LAMP+phpmyadmin环境

??二. dockerfile编写

  • apache变体apache:7.4-apache的dockerfile文件php-apache_dockerfile:

#基础镜像
FROM php:7.4-apache

#环境变量,用于登录MySQL
ENV MYSQL_ROOT_PASSWORD 6666

#下载php扩展mysqli,用于对数据库进行操作
RUN apt-get update&&apt-get install -y         libfreetype6-dev         libjpeg62-turbo-dev         libpng-dev     && docker-php-ext-configure gd --with-freetype --with-jpeg     && docker-php-ext-install -j$(nproc) mysqli

ps:搁这跳了个小坑,为了下载核心扩展mysqli,在build过程中,需要先对软件源进行更新,即apt-get update,如果使用原始软件源地址直接进行apt-get update,速度很慢或者更新失败。
  分析:由于该镜像是基于Debian系统的,apt-get的软件源地址是官网地址,属于外网,造成apt-get的更新所需的部分资源获取速度比较慢,导致apt-get更新卡顿。
  解决方法:想到之前在本机上对apt-get更新时也会遇到卡顿的情况,当时是用软件源镜像加速处理的,于是顺藤摸瓜,尝试着用使用镜像加速的方法去解决:首先查看该镜像的dockerfile文件发现,该镜像是基于Debian构建的,通过查阅资料找到了Debian更换软件源实现镜像加速的方法(方法如下图),在php-apache_dockerfileRUN中加入sed -i ‘s/deb.debian.org/mirrors.ustc.edu.cn/g‘ /etc/apt/sources.list ,更换软件源。接着重新build,安装速度直接起飞,卡顿问题完美解决。
利用docker-compose搭建LAMP+phpmyadmin环境
  修改之后的php-apache_dockerfile

#基础镜像
FROM php:7.4-apache

#环境变量,用于登录MySQL
ENV MYSQL_ROOT_PASSWORD 6666

#下载php扩展mysqli,用于对数据库进行操作
RUN sed -i ‘s/deb.debian.org/mirrors.ustc.edu.cn/g‘ /etc/apt/sources.list && apt-get clean&& apt-get update&&apt-get install -y         libfreetype6-dev         libjpeg62-turbo-dev         libpng-dev     && docker-php-ext-configure gd --with-freetype --with-jpeg     && docker-php-ext-install -j$(nproc) mysqli
  • MySQL_dockerfile:

#基础镜像
FROM mysql

#作者信息
MAINTAINER by lxc(https://www.cnblogs.com/lxccccc/)

#设置root密码
ENV MYSQL_ROOT_PASSWORD 6666

#设置不可免密登录
ENV MYSQL_ALLOW_EMPTY_PASSWORD no

#为docker_mysql创建数据库
ENV MYSQL_DATABASE docker_mysql

#创建新用户
ENV MYSQL_USER=docker
ENV MYSQL_PASSWORD=123456
  • phpmyadmin_dockerfile:

#基础镜像
FROM phpmyadmin/phpmyadmin

#作者信息
MAINTAINER by lxc(https://www.cnblogs.com/lxccccc/)

??三.docker-compose配置文件docker-compose.yml

  • docker-compose.yml:

version: ‘3.7‘

services:
  #构建mysql服务
  mysql:
    image: mysql:lxc #容器运行使用的镜像
    build: 
      context: .
      dockerfile: MySQL_dockerfile
    container_name: php_mysql #定义容器名称
    ports:
      - "3306:3306"  #映射端口,格式为 "主机端口:容器端口"
  #构建php变体php-apache服务
  web:
    image: php:lxc
    build:
      context: .
      dockerfile: php-apache_dockerfile
    container_name: php-apache
    depends_on:   #设置依赖的服务
      - mysql
    volumes:
      - ./www/:/var/www/html/ #将主机中的目录挂载到容器中的工作目录,易于对web服务的管理
    ports:
      - "8080:80"
  #构建phpmyadmin服务
  phpmyadmin:
    image: phpmyadmin:lxc
    build:
      contest: .
      dockerfile: phpmyadmin_dockerfile
    environment:
      PMA_HOST: php_mysql #设置所连接的MySQL服务器名称
    container_name: phpmyadmin
    depends_on:
      - mysql
      - web
    ports:
      - "8081:80"
  • 其他文件

创建文件夹www,将web代码存放该在文件夹中,并且在docker-compose.yml中将该目录挂载到容器的工作目录下,实现数据持久化,方便对容器运行时的管理。www主要包括两个php文件,一个是index.php,用于验证php服务是否成功开启;另一个是mysql.php,用于实现连接操作MySQL数据库,包括数据的增删改查等基本操作。

index.php:

<!-- ./php/index.php -->

<html>
    <head>
        <title>phpinfo</title>
    </head>

    <body>
        <?php
            echo phpinfo(); #显示php信息
        ?>
    </body>
</html>

mysql.php:

<html>
<body>
<head>
	<title>Mysql Test</title>
</head>
<?php
$servername = "php_mysql";#这里的数据库服务器名称为MySQL容器的名称
$username = "root";
$password = $_ENV["MYSQL_ROOT_PASSWORD"];
$dbname = "mydb";

function ShowData($result){ //显示数据的函数
   global $servername, $username, $password, $dbname;
   $conn = new mysqli($servername, $username, $password, $dbname);
   $sql = "select * from MyTable;";
   $result = $conn->query($sql);
   $table = "<table border=‘1‘ cellspacing=‘0‘  width=‘200‘ height=‘50‘>";
   $table .="<tr align=‘center‘><td>ID</td><td>Name</td><td>Sex</td></tr>";
    // 输出数据
    for($i=1;$i<=$result->num_rows;$i++){ //行
	$table.="<tr align=‘center‘>";
	$row = $result->fetch_assoc();  //列
	$table .= "<td>" . $row[‘ID‘] ."</td>" . "<td>" . $row[‘NAME‘] ."</td>" . "<td>" . $row[‘SEX‘] ."</td>";

    $table.="</tr>";
    }
$table.="</table>";
echo $table;
}

// 创建连接
$conn = new mysqli($servername, $username, $password);
// 检测连接
if ($conn->connect_error) {
    die("连接失败: " . $conn->connect_error . "<br>");
} 
else{
    echo "连接成功!<br>";
}
// 创建数据库mydb
$sql = "DROP DATABASE "  . " IF EXISTS " . $dbname . ";create DATABASE " .$dbname;

// 检测数据库是否创建成功
if ($conn->multi_query($sql)){
    echo "create database " . $dbname . " successfully!<br>";
}
else{
    echo "failed:" . $conn->error . "<br>";
}

sleep(1);
// 创建连接,连接到数据库
$conn = new mysqli($servername, $username, $password,$dbname);

// 建表
$sql = "CREATE TABLE MyTable(
    ID BIGINT(10) NOT NULL PRIMARY KEY,
    NAME NVARCHAR(10) NOT NULL,
    SEX NVARCHAR(6),
    CHECK (SEX=‘male‘ or SEX=‘female‘ or SEX=‘男‘ or SEX=‘女‘)
)";
// 检测建表是否成功
if ($conn->query($sql) === TRUE){
    echo "create table MyTable successfully!<br>";
}
else{
    echo "failed:" . $conn->error . "<br>";
}

// 向表中插入数据
$sql = "INSERT INTO MyTable 
   VALUES (1,‘张三‘,‘male‘);";
$sql .= "INSERT INTO MyTable 
   VALUES (2,‘李四‘,‘男‘);";
$sql .= "INSERT INTO MyTable 
   VALUES (3,‘小兰‘,‘female‘);";

// 检测数据是否成功插入
if ($conn->multi_query($sql)){
    echo "insert data into MyTable successfully!<br>";
}
else{
    echo "failed:" . $conn->error . "<br>";
}

sleep(1);
echo "<br>查表:<br>";
ShowData($result);


// 修改数据
sleep(1);
echo "<br>修改数据:将李四的‘Sex‘改为‘male‘<br>";
$conn = new mysqli($servername, $username, $password, $dbname);
$sql = "UPDATE MyTable SET SEX=‘male‘ WHERE NAME=‘李四‘;";
$result = $conn->query($sql);
echo $result->num_rows;
ShowData($result);

// 增加数据
sleep(1);
echo "<br>增加数据:<br>";
$conn = new mysqli($servername, $username, $password, $dbname);
$sql = "INSERT INTO MyTable 
   VALUES (4,‘小红‘,‘female‘);";
$result = $conn->query($sql);
echo $result->num_rows;
ShowData($result);

// 删除数据
sleep(1);
echo "<br>删除数据:删除名为张三的信息<br>";
$conn = new mysqli($servername, $username, $password, $dbname);
$sql = "DELETE FROM MyTable WHERE NAME=‘张三‘";
$result = $conn->query($sql);
echo $result->num_rows;
ShowData($result);
$conn->close();
?>
</body>
</html>

将以上所有文件放到及文件夹同一个文件夹下(我这里放到名为LAMP的文件目录下),文件结构如下:
利用docker-compose搭建LAMP+phpmyadmin环境
  使用命令docker-compose up --build进行镜像的构建及多容器的开启:

  • 镜像的构建
    利用docker-compose搭建LAMP+phpmyadmin环境

  • 多容器的开启
    利用docker-compose搭建LAMP+phpmyadmin环境

??四.服务验证

  1. php-apache服务验证
    在浏览器中输入0.0.0.0:8080,访问php-apache服务,页面显示index.php的内容信息
    利用docker-compose搭建LAMP+phpmyadmin环境
      查看mysqli的信息:
    利用docker-compose搭建LAMP+phpmyadmin环境

2.php连接MySQL
在浏览器中输入0.0.0.0:8080/mysql.php,访问mysql.php,实现数据库的连接管理功能
利用docker-compose搭建LAMP+phpmyadmin环境

3.phpmyadmin服务验证
在浏览器中输入0.0.0.0:8081,访问phpmyadmin服务,对数据库进行管理
  需要注意:如果我们没有设置所要连接的MySQL服务名称,就会出现无法连接到MySQL数据库的错误:
利用docker-compose搭建LAMP+phpmyadmin环境
  原因:php要连接docker中运行的mysql是不能用localhost, 127.0.0.1来连接的,因为每个docker运行容器的localhost 127.0.0.1都是自己容器本身,不是mysql容器,需要修改成母机 IP,或者是mysql容器名称。因此,需要在docker-compose.yml中的phpmyadmin服务中指定phpmyadmin所连接的MySQL服务名称。
  方法:将环境变量PMA_HOST赋值为MySQL容器名称:

environment:
     PMA_HOST: php_mysql #这里为MySQL服务的容器名称

重新运行命令docker-compose up --build,重新构建所有镜像,启动多容器,再次访问phpmyadmin,输入设置的root用户及密码,成功登录到MySQL数据库可以看到新建的"mydb"数据库,:
利用docker-compose搭建LAMP+phpmyadmin环境
  对该库下的MyTable表进行简单地更新操作:
利用docker-compose搭建LAMP+phpmyadmin环境
利用docker-compose搭建LAMP+phpmyadmin环境

至此,利用docker-compose成功搭建LAMP+phpmyadmin环境。

??五.小结

本次实践所花费的时间,断断续续加起来差不多有两天,主要包括学习docker-compose的使用、docker-compose.yml的编写、php连接MySQL的基础用法等。通过搭建LAMP环境,学习了docker-compose的基本用法,感受了docker-compose构建多个镜像、运行多容器的机制,对docker的功能有了进一步的了解。同时也认识了web服务,对web服务的整体框架有了初步了解,希望在接下来的开发中能够学以致用。

相关推荐