2020系统综合实践 第3次实践作业
一个最终的应用通常需要组装多个容器提供的多个服务。以web服务为例,需要完成web服务器、数据库、开发程序等服务的组装,典型的如LAMP(Linux+Apache+Mysql+PHP)或LNMP(Linux+Nginx+Mysql+PHP)。Docker compose是作为定义和运行多容器的工具,用户可以使用 YML 文件来配置应用程序需要的所有服务。本次作业需要各位实践Docker compose,各位可以在第二次实践作业的基础之上开展,要求如下:
(1)完成Docker-compose的安装
我这里采用的是在Linux系统上安装Docker-compose,具体步骤如下:
- 运行以下命令以下载Docker Compose的当前稳定版本(要安装其他版本的Compose,请替换1.25.5为要使用的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
- 将可执行权限应用于二进制文件:
sudo chmod +x /usr/local/bin/docker-compose
- 创建指向
/usr/bin
或路径中任何其他目录的符号链接:
sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose
- 测试安装是否成功:
$ docker-compose --version
若可以看到docker-compose的版本则说明安装成功:
(2)Dockerfile编写
要求:
LNMP/LAMP选择一种;
分别构建web、php应用、数据库等镜像服务,php镜像亦有提供php:
提示:php连接数据库需要安装必要的核心扩展部件(PHP Core Extensions)安装方法可参考官方镜像介绍。
我这里选择的是LNMP(Linux+Nginx+Mysql+PHP)来分别构建web、php应用、数据库等镜像服务。具体步骤如下所示:
1.由于我们做实验的过程中需要用到PHP,所以需要先拉取一个PHP镜像:
sudo docker pull php:7.4-fpm
2.在系统主目录下创建一个docker_compose文件夹,此文件夹用于存放实验中我们需要用到的各种配置文件,docker_compose中的具体配置文件如下所示:
在创建好相应的文件后,可以使用如下命令来查看docker_compose文件中的目录结构:
cyk@cyk-vir tual-machine: ~/docker_ compose$ tree
3.编写相应的配置文件:
- 编写dockerfile_nginx:
#基础镜像
FROM nginx
#作者信息
MAINTAINER cyk2430
#声明暴露的端口
EXPOSE 3030
- 编写default.conf:
server {
listen 3030; #修改映射端口
server_name localhost;
location / {
root /home/cyk/docker_compose/web/html; #修改工作目录
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
location ~ .php$ {
root /home/cyk/docker_compose/web/php; #修改工作目录
fastcgi_pass cykphp:9000; #修改为容器名
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
在编写default.conf配置文件时,要注意修改的映射端口要与dockerfile_nginx文件中声明暴露的端口相一致。
- 编写dockerfile_php:
#基础镜像
FROM php:7.4-fpm
#作者信息
MAINTAINER cyk2430
FROM php:7.4-fpm
RUN apt-get update && apt-get install -y
libfreetype6-dev
libjpeg62-turbo-dev
libpng-dev
&& docker-php-ext-install pdo_mysql
&& docker-php-ext-configure gd --with-freetype --with-jpeg
&& docker-php-ext-install -j$(nproc) gd
- 编写dockerfile_mysql:
#基础镜像
FROM mysql
#作者信息
MAINTAINER cyk2430
#设置root密码
ENV MYSQL_ROOT_PASSWORD 123456
#设置不可免密登录
ENV MYSQL_ALLOW_EMPTY_PASSWORD no
- 编写docker-compose.yml:
version: "3"
services:
nginx:
image: cyknginx_image #指定镜像名
container_name: cyknginx #指定容器名
build:
context: .
dockerfile: dockerfile_nginx #指定dockerfile文件
ports:
- "80:3030" #修改端口映射,要注意与之前声明的端口匹配
volumes:
- ./web:/home/cyk/docker_compose/web/html
- ./default.conf:/etc/nginx/conf.d/default.conf #配置文件
php:
image: cykphp_image
container_name: cykphp
build:
context: .
dockerfile: dockerfile_php
environment:
MYSQL_PASSWORD: 123456
volumes:
- ./web:/home/cyk/docker_compose/web/php
mysql:
image: cyksql_image
container_name: cyksql
build:
context: .
dockerfile: dockerfile_mysql
ports:
- "3306:3306"
volumes:
- ./mysql_data:/var/lib/mysql
- 在Web文件夹下创建index.html和index.php两个文件:
编写index.html(文件里的内容可由用户自己指定):
<!DOCTYPE html>
<html>
<head>
<title>Web</title>
</head>
<body>
<h1 style = "text-align: center">Hello 031702430!<br/>
Welcome to My Web Server.</h1>
</body>
</html>
编写index.php:
<?php phpinfo();?>
- source.list文件是在后面构建PHP镜像时,通过进行换源用于提高下载速度的(可根据需要自行取舍),具体内容如下所示:
deb https://mirrors.tuna.tsinghua.edu.cn/debian/ buster main contrib non-free
deb https://mirrors.tuna.tsinghua.edu.cn/debian/ buster-updates main contrib non-free
deb https://mirrors.tuna.tsinghua.edu.cn/debian/ buster-backports main contrib non-free
deb https://mirrors.tuna.tsinghua.edu.cn/debian-security buster/updates main contrib non-free
(3)使用Compose实现多容器运行机制
- 编写compose文件,完成上述LNMP/LAMP的微服务组合部署。
- 参考资料:Get started with Docker Compose
1.在相应的配置文件都编写好之后,我们就可以完成上述LNMP的微服务组合部署了。此时需要在刚刚创建的docker_compose文件夹下打开终端,运行如下命令:
sudo docker-compose up -d -- build
(需要注意此过程可能会十分的漫长,大家要耐心等待,我印象中等待这一步完成花了将近二三十分钟左右的时间,这里我没通过进行换源用于提高下载速度,也是在后面班级群里有同学提问才知道的。。。)
2.在相应的镜像构建成功后,我们可以查看此时的镜像和容器列表:
3.在Firefox浏览器中访问localhost/index.html,即可看到之前在Web文件下创建index.html里的内容:
4.在Firefox浏览器中访问localhost/index.php,可查看PHP配置信息:
(4)服务测试
要求和提示:
- 包括但不限于测试数据库连接、数据库新建、表新建、表记录的插入修改和删除是否成功(pdo或mysqli均可);
- 相关测试代码可直接参考PHP与MySQL的教程。
1.测试数据库连接:
- 此时需要先编辑index.php文件:
<?php
$servername = "cyksql"; #servername 需要根据自己的实际情况配置
$username = "root";
$password = "123456";
try {
$conn = new PDO("mysql:host=$servername", $username, $password);
echo "恭喜连接成功";
}
catch(PDOException $e)
{
echo $e->getMessage();
}
- 打开Firefox浏览器,访问localhost/index.php进行测试:
2.数据库新建:
- 先编辑index.php文件:
<?php
$servername = "cyksql";
$username = "root";
$password = "123456";
try {
$conn = new PDO("mysql:host=$servername", $username, $password);
// 设置 PDO 错误模式为异常
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sql = "CREATE DATABASE cyk2430DB"; //指定创建的数据库名,为cyk2430DB
// 使用 exec() ,因为没有结果返回
$conn->exec($sql);
echo "数据库创建成功<br>";
}
catch(PDOException $e)
{
echo $sql . "<br>" . $e->getMessage();
}
$conn = null;
?>
-
打开Firefox浏览器,访问localhost/index.php进行测试:
-
在命令行中输入以下命令,查看数据库:
sudo docker exec -it cyksql /bin/bash
mysql -u root -p
show databases;
此时可以看见数据库列表中包含了我们之间新建的数据库cyk2430DB:
3.表新建:
- 先编辑index.php文件:
<?php
$servername = "cyksql";
$username = "root";
$password = "123456";
$dbname="cyk2430DB";
try {
$conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
// 设置 PDO 错误模式,用于抛出异常
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// 使用 sql 创建数据表
$sql = "CREATE TABLE student ( //创建student表,包含sno、name1
sno VARCHAR(10) PRIMARY KEY,
name VARCHAR(7) NOT NULL,
sex VARCHAR(2) NOT NULL,
age SMALLINT NOT NULL
)";
// 使用 exec() ,没有结果返回
$conn->exec($sql);
echo "数据表 student 创建成功";
}
catch(PDOException $e)
{
echo $sql . "<br>" . $e->getMessage();
}
$conn = null;
?>
- 在命令行中输入以下命令,查看新建的student表:
4.表记录的插入:
- 先编辑index.php文件:
<?php
$servername = "cyksql";
$username = "root";
$password = "123456";
$dbname="cyk2430DB"; #变量设置
try {
$conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// 开始事务
$conn->beginTransaction();
// SQL 语句
$conn->exec("INSERT INTO student (sno,name,sex,age)
VALUES ('031702430', 'cyk','M',21)");
$conn->exec("INSERT INTO student (sno,name,sex,age)
VALUES ('031702428', 'phd','M',23)");
$conn->exec("INSERT INTO student (sno,name,sex,age)
VALUES ('031702401', 'xh','W',24)");
// 提交事务
$conn->commit();
echo "恭喜学生信息导入成功!";
}
catch(PDOException $e)
{
echo $sql . "<br>" . $e->getMessage();
}
$conn = null;
?>
-
打开Firefox浏览器,访问localhost/index.php进行测试:
-
使用数据库查询语句select * from student;查看student表中的数据:
5.表记录的修改:
- 先编辑index.php文件:
<?php
$servername = "cyksql";
$username = "root";
$password = "123456";
$dbname="cyk2430DB"; #变量设置
try {
$conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// 开始事务
$conn->beginTransaction();
// SQL 语句(修改student表中的数据)
$conn->exec("UPDATE student SET sno='031702430' WHERE age=25");
$conn->exec("UPDATE student SET name='phd' WHERE age=20");
// 提交事务
$conn->commit();
echo "修改学生信息成功!";
}
catch(PDOException $e)
{
echo $sql . "<br>" . $e->getMessage();
}
$conn = null;
?>
- 再次使用数据库查询语句select * from student;查看student表中的数据,可看到数据修改成功:
6.删除表中的数据:
- 编辑index.php文件:
<?php
$servername = "cyksql";
$username = "root";
$password = "123456";
$dbname="cyk2430DB"; #变量设置
try {
$conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// 开始事务
$conn->beginTransaction();
// SQL 语句(删除student表中的数据)
$conn->exec("DELETE FROM student where sno='031702401'");
// 提交事务
$conn->commit();
echo "删除学生信息成功!";
}
catch(PDOException $e)
{
echo $sql . "<br>" . $e->getMessage();
}
$conn = null;
?>
- 查看student表中的数据,可发现相应记录已成功删除:
(5)选做
- 增加一个phpmyadmin容器,实现web端的数据库管理。
1.先拉取相应的镜像:
sudo docker pull phpmyadmin/phpmyadmin
2.在之前的docker_compose文件夹下新建一个dockerfile_phpmyadmin文件,并进行编辑:
#基础镜像
FROM phpmyadmin/phpmyadmin
#作者信息
MAINTAINER cyk2430
#声明暴露的端口
EXPOSE 8080
重新查看docker_compose文件夹下的目录结构:
3.修改之前创建的docker-compose.yml文件(主要是新加了phpmyadmin这个服务):
version: "3"
services:
phpmyadmin:
image: cykphpmyadmin_image
container_name: cykphpmyadmin
build:
context: .
dockerfile: dockerfile_phpmyadmin
ports:
- "8080:80" # phpmyadmin默认监听80
environment:
PMA_HOST: mysql #指定mysql服务所在的host
nginx:
image: cyknginx_image #指定镜像名
container_name: cyknginx #指定容器名
build:
context: .
dockerfile: dockerfile_nginx #指定dockerfile文件
ports:
- "80:3030" #修改端口映射
volumes:
- ./web:/home/cyk/docker_compose/web/html
- ./default.conf:/etc/nginx/conf.d/default.conf #配置文件
php:
image: cykphp_image
container_name: cykphp
build:
context: .
dockerfile: dockerfile_php
environment:
MYSQL_PASSWORD: 123456
volumes:
- ./web:/home/cyk/docker_compose/web/php
mysql:
image: cyksql_image
container_name: cyksql
build:
context: .
dockerfile: dockerfile_mysql
ports:
- "3306:3306"
volumes:
- ./mysql_data:/var/lib/mysql
4.接着在docker_compose文件夹下打开终端,重新运行docker-compose:
sudo docker-compose up -d
5.用浏览器访问http://localhost:8080/,并用自己的root的账号密码登录:
6.在登陆后,从左边的目录中选择cyk2430DB数据库,查看Student表:
此时我们就可以对数据库进行增删改查等一系列操作:
- 向Student表插入新纪录:
- 删除Student表中的记录:
(6)实验小结:
1.记录完成作业所花的时间:
作业名称 | 耗时(小时) |
---|---|
Docker-compose的安装 | 0.3 |
Dockerfile编写以及使用Compose实现多容器运行机制 | 4 |
服务测试 | 3 |
增加phpmyadmin容器 | 1 |
博客编写 | 3 |
总计 | 11.3 |
2.记录实验过程的主要问题和解决方法:
(1)在实验过程中,我遇到的第一个问题是在使用命令sudo docker-compose up -d -- build来构建相应的镜像时,时不时地会卡在某一个地方,如下所示:
在这一步我卡了很久,浪费了将近有一个多小时(欲哭无泪。。。)我刚开始以为可能是网络的原因,但是尝试换了不同的网络后还是这样。。后面询问了老师和同学后知道了可以使用更换国内源来解决dockerfile构建速度过慢的问题,具体的做法是在Dockerfile的开头中添加如下两句代码:
RUN sed -i s@/archive.ubuntu.com/@/mirrors.aliyun.com/@g /etc/apt/sources.list
RUN apt-get clean
这样子通过换源的方法就可以解决dockerfile构建速度过慢的问题了(虽然我自己做的时候是慢慢等待,花了将近30分钟左右的时间才成功构造出镜像,但是这个加速的方法我还是想分享一下,具体可参考链接:https://www.cnblogs.com/PyKK2019/p/11062019.html)
(2)遇到的第二个比较坑的问题就是在第二步dokerfile文件的编写中,有一些工作目录的路径没有配置正确,这样子就导致了之后通过浏览器访问时会出现404 not found的问题,在这里我说一下default.conf和docker-compose.yml这两个配置文件需要注意的问题:
在default.conf文件中root需要设置成Web文件夹下index.html文件所在的位置,我建议的做法是先直接找到index.html这一个文件,然后右击属性,把里面的文件位置直接给复制下来贴上去,这样子比较不容易出错。而php中的root就是设置成Web文件夹下index.php文件所在的位置。docker-compose.yml文件中要注意的路径的设置我也标注出来了,具体设置方法同上。
(3)第三个问题就是在命令执行过程中,出现了进程被占用的错误,如下所示:
E: 无法获得锁 /var/lib/dpkg/lock-frontend - open (11: 资源暂时不可用)
E: 无法获取 dpkg 前端锁 (/var/lib/dpkg/lock-frontend),是否有其他进程正占用它?
网上参考的办法是在终端中输入:
sudo rm /var/cache/apt/archives/lock
sudo rm /var/lib/dpkg/lock
来进行解锁,但是我这样子做了之后还是显示进程被占用,之后重启一下Ubuntu就可以了。
3.实验感想:
我做这次实验大约花了一个下午加一个晚上的时间,然后编写博客花了半个早上,由于之前很多比较坑的问题都已经有同学找到了解决办法,所以这次实验的总体还算是比较顺利的。(这里要感谢班级群里很多大佬的热心回答)但尽管如此,做实验的过程中一定要细心,比如dockerfile文件中不小心写错一个地方都可能会导致前功尽弃,这次实验很多细节问题都需要去留意。总体而言,通过这次实验,我收获了很多东西,例如学会了web服务器、数据库、开发程序等服务的组装(LNMP(Linux+Nginx+Mysql+PHP)),也顺便巩固了之前MySQL数据库的相关操作,同时通过选做部分学会了利用增加phpmyadmin容器来实现web端的数据库管理。经过这几次实验,我觉得做实验不仅是一个学习新知识的过程,更是一个学会思考、学会发现问题然后解决问题的过程,简单来说就是痛并快乐着!