2020系统综合实践 第3次实践作业

2020系统综合实践 第3次实践作业

一个最终的应用通常需要组装多个容器提供的多个服务。以web服务为例,需要完成web服务器、数据库、开发程序等服务的组装,典型的如LAMP(Linux+Apache+Mysql+PHP)或LNMP(Linux+Nginx+Mysql+PHP)。Docker compose是作为定义和运行多容器的工具,用户可以使用 YML 文件来配置应用程序需要的所有服务。本次作业需要各位实践Docker compose,各位可以在第二次实践作业的基础之上开展,要求如下:

(1)完成Docker-compose的安装

参考资料:Install 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:-apache的变体;

提示: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实现多容器运行机制

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端的数据库管理。经过这几次实验,我觉得做实验不仅是一个学习新知识的过程,更是一个学会思考、学会发现问题然后解决问题的过程,简单来说就是痛并快乐着!

原文地址:https://www.cnblogs.com/chenyoukun/p/12850064.html