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


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

    一、完成Docker-compose的安装

    参考资料:Install Docker Compose

    1.Linux 上我们可以从 Github 上下载它的二进制包来使用,但是速度会有点慢就换另一个源

    sudo curl -L "https://get.daocloud.io/docker/compose/releases/download/1.24.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
    

    2.将可执行权限应用于二进制文件:

    sudo chmod +x /usr/local/bin/docker-compose
    

    3.创建软链:

    sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose
    

    4.测试是否安装成功:

    docker-compose --version
    

    注意: 对于 alpine,需要以下依赖包: py-pip,python-dev,libffi-dev,openssl-dev,gcc,libc-dev,和 make。

    Alpine是什么呢?

    Alpine Linux是一个面向安全的轻型的Linux发行版。

    Alpine Linux采用了 musl libc 和 busybox以减小系统的体积和运行时资源消耗。

    在保持瘦身的同时,Alpine Linux还提供了自己的包管理工具apk。

    关键的是,相比于其他Linux的Docker镜像,它的容量非常小,只有5MB。

    二、Dockerfile编写

    要求:

    LNMP/LAMP选择一种;

    分别构建web、php应用、数据库等镜像服务,php镜像亦有提供php:-apache的变体;

    提示:php连接数据库需要安装必要的核心扩展部件(PHP Core Extensions)安装方法可参考官方镜像介绍。

    选择LNMP

    1.创建dockerfile_nginx:

    FROM nginx:latest
    
    EXPOSE 8010
    

    2.创建dockerfile_php:

    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
    

    3.创建dockerfile_mysql:

    FROM mysql:5.7
    
    ENV MYSQL_ROOT_PASSWORD 123456
    
    ENV MYSQL_ALLOW_EMPTY_PASSWORD no
    

    4.创建dockerfile-phpmyadmin

    FROM phpmyadmin/phpmyadmin      
    
    EXPOSE 8050
    

    5.创建index.html

    6.创建default.conf

    server {
    
      listen    8010;            #监听8010端口
    
      server_name  localhost;        #定义使用www.xx.com访问
    
     
    
      location / {              #默认请求
    
    ​    root  /home/docker-web/html;   #定义服务器的默认网站根目录位置
    
    ​    index  index.html index.htm;    #定义首页索引文件名称
    
      }
    
    #error_page  404        /404.html;       #定义错误提示页面
    
     
    
    # redirect server error pages to the static page /50x.html  #重定向服务器错误页面
    
     
    
      error_page  500 502 503 504  /50x.html; #定义错误提示页面
    
      location = /50x.html {
    
    ​    root  /usr/share/nginx/html;
    
      }
    
      
    
      location ~ .php$ {      #通过PHP脚本sphp:9000的FastCGI服务器监听
    
    ​    root     /home/docker-web/php;      #修改工作目录
    
    ​    fastcgi_pass  sphp:9000;     #修改为容器名
    
    ​    fastcgi_index  index.php;
    
    ​    fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name; 
    
    ​    include     fastcgi_params;
    
      }
    
    }
    

    文件结构如图:

    三、使用Compose实现多容器运行机制

    编写compose文件,完成上述LNMP/LAMP的微服务组合部署。

    参考资料:Get started with Docker Compose

    创建docker-compose.yml

    version: "3"
    
    services:
    
     nginx:
    
     image: snginx_image         #指定镜像名
    
     container_name: snginx       #指定容器名
    
     build:
    
      context: .
    
      dockerfile: dockerfile_nginx    #指定dockerfile文件
    
     ports:
    
      - "80:8010"            #修改端口映射
    
     volumes:
    
      - ./web:/home/docker-web/html         #挂载容器卷,本地/容器内修改文件后,另一方都会同步更新;
    
      - ./default.conf:/etc/nginx/conf.d/default.conf   #挂载配置文件
    
     
    
     php:
    
     image: sphp_image 
    
     container_name: sphp 
    
     build:
    
      context: .
    
      dockerfile: dockerfile_php 
    
     environment:
    
      MYSQL_PASSWORD: 123456       #设置好环境变量,在php代码中使用变量名直接引用
    
     volumes:
    
      - ./web:/home/docker-web/php          #挂载工作目录到本机web目录
    
     
    
     mysql:
    
     image: mysql_image 
    
     container_name: mysql
    
     build:
    
      context: .
    
      dockerfile: dockerfile_mysql
    
     ports:
    
      - "3306:3306"
    
     
    
     volumes:
    
      - ./mysql_data:/var/lib/mysql    #挂载容器卷,实现数据同步,防止数据丢失
    
     
    
     phpmyadmin:
    
     image: myphpmyadmin_image
    
     container_name: myphpmyadmin
    
     build: 
    
      context: .
    
      dockerfile: dockerfile_phpmyadmin
    
     ports: 
    
      - "8050:80" # phpmyadmin默认监听80
    
     environment:
    
     
    
     PMA_HOST: mysql           #指定mysql服务所在的host
    

    Localhost 打开了docker-compose web index.html

    Localhost:8050 打开了phpmyadmin

    四、服务测试

    要求和提示:

    包括但不限于测试数据库连接、数据库新建、表新建、表记录的插入修改和删除是否成功(pdo或mysqli均可);

    相关测试代码可直接参考PHP与MySQL的教程。

    https://www.runoob.com/php/php-mysql-connect.html

    PDO 应用在 12 种不同数据库中, MySQLi 只针对 MySQL 数据库

    1.测试数据库连接

    (1)编辑index.php文档

    <?php
    
    $servername = "mysql";   
    
    $username = "root";
    
    $password = "123456";   
    
     
    
    try {
    
      $conn = new PDO("mysql:host=$servername", $username, $password);
    
      echo "连接成功"; 
    
    }
    
    catch(PDOException $e)
    
    {
    
      echo $e->getMessage();
    
    }
    

    (2)测试

    2.数据库新建

    (1)编辑index.php文档

    <?php
    
    $servername = "mysql";
    
    $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 myDBPDO";
    
     
    
      // 使用 exec() ,因为没有结果返回
    
      $conn->exec($sql);
    
     
    
      echo "数据库创建成功<br>";
    
    }
    
    catch(PDOException $e)
    
    {
    
      echo $sql . "<br>" . $e->getMessage();
    
    }
    
     
    
    $conn = null;
    
    ?>
    

    (2)测试

    3.表新建

    (1)编辑index.php文档

    <?php
    
    $servername = "mysql";
    
    $username = "root";
    
    $password = "123456";
    
    $dbname = "myDBPDO";
    
     
    
    try {
    
      $conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
    
      // 设置 PDO 错误模式,用于抛出异常
    
      $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    
     
    
      // 使用 sql 创建数据表
    
      $sql = "CREATE TABLE stu (
    
      ID INT(9) UNSIGNED AUTO_INCREMENT PRIMARY KEY, 
    
      NAME VARCHAR(30) NOT NULL,
    
      MAJOR VARCHAR(30) NOT NULL
    
      )";
    
     
    
      // 使用 exec() ,没有结果返回 
    
      $conn->exec($sql);
    
      echo "数据表 stu 创建成功";
    
    }
    
    catch(PDOException $e)
    
    {
    
      echo $sql . "<br>" . $e->getMessage();
    
    }
    
     
    
    $conn = null;
    
    ?>
    

    (2)测试

    4.表记录的插入

    (1)编辑index.php文档

    <?php
    
    $servername = "mysql";
    
    $username = "root";
    
    $password = "123456";
    
    $dbname="myDBPDO";   
    
     
    
    try {
    
      $conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
    
      // set the PDO error mode to exception
    
      $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    
     
    
      // 开始事务
    
      $conn->beginTransaction();
    
      // SQL 语句
    
      $conn->exec("INSERT INTO stu (ID, NAME, MAJOR) 
    
      VALUES ('031702507', 'hh', 'CS')");
    
      $conn->exec("INSERT INTO stu (ID, NAME, MAJOR) 
    
      VALUES ('03172508', 'xs', 'CS')");
    
      $conn->exec("INSERT INTO stu (ID, NAME, MAJOR) 
    
      VALUES ('031702624', 'zz', CS')");
    
      // 提交事务
    
      $conn->commit();
    
      echo "新记录插入成功";
    
    }   
    
    catch(PDOException $e)
    
    {
    
      // 如果执行失败回滚
    
      $conn->rollback();
    
      echo $sql . "<br>" . $e->getMessage();
    
    }
    
     
    
    $conn = null;
    
    ?>
    

    (2)测试

    5.表记录的修改

    (1)编辑index.php文档

    <?php
    
    $servername = "mysql";
    
    $username = "root";
    
    $password = "123456";
    
    $dbname="myDBPDO";   
    
     
    
    try {
    
      $conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
    
      // set the PDO error mode to exception
    
      $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    
      // SQL 语句
    
      $conn->exec("UPDATE stu SET MAJOR='Computer Science' WHERE ID=031702507");
    
      echo "记录修改成功";
    
    }   
    
    catch(PDOException $e)
    
    {
    
      // 如果执行失败回滚
    
      $conn->rollback();
    
      echo $sql . "<br>" . $e->getMessage();
    
    }
    
     
    
    $conn = null;
    
    ?>
    

    (2)测试

    6.表记录的删除

    (1)编辑index.php文档

    <?php
    
    $servername = "mysql";
    
    $username = "root";
    
    $password = "123456";
    
    $dbname="myDBPDO";   
    
     
    
    try {
    
      $conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
    
      // set the PDO error mode to exception
    
      $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    
      // SQL 语句
    
    $conn->exec("DELETE FROM stu where ID=03172508");
    
      echo "记录删除成功";
    
    }   
    
    catch(PDOException $e)
    
    {
    
      // 如果执行失败回滚
    
      $conn->rollback();
    
      echo $sql . "<br>" . $e->getMessage();
    
    }
    
     
    
    $conn = null;
    
    ?>
    

    (2)测试

    五、选做

    增加一个phpmyadmin容器,实现web端的数据库管理。

    在上面二、就已经写了dockerfile_phpmyadmin和docker-compose.yml

    (1)从localhost:8050端口进入

    (2)查看myDBPDO数据库中的stu表

    (3)表记录的插入

    (4)表记录的修改

    (5)表记录的删除

    六、小结

    1.主要问题和解决办法

    问题1:

    解决方法:因为YAML使用缩进表示层级关系;所以检查缩进关系。成功解决问题。
    

    知识储备:

    YAML

    Compose 是用于定义和运行多容器 Docker 应用程序的工具。通过使用一个命令,就可以从 YML 文件配置中创建并启动应用程序需要的所有服务。

    基本语法

    大小写敏感;

    使用缩进表示层级关系;

    缩进不允许使用tab,只允许空格。缩进的空格数不重要,只要相同层级的元素左对齐即可;

    '#'表示注释。

    问题2:晚上下载的时候一直卡在pull phpmyadmin,甚至下了一晚上都还么下完。

    解决方法:白天的时候添加多个国内镜像源,再试一次就好了。(得出神秘的结论,晚上不适合做实验
    
    sudo vi /etc/docker/daemon.json
    
    {"registry-mirrors":["https://docker.mirrors.ustc.edu.cn/","https://hub-mirror.c.163.com","https://registry.docker-cn.com"],}
    
    systemctl restart docker.service
    

    问题3:docker-compose up 完成后还是不能够访问

    解决办法:重新检查一下前面写的dockerfile、yml、default.conf文件,发现映射端口80被两个服务占用,,将其中一个改成别的就可以了。
    

    问题4:通过 phpinfo() 查看PDO是否安装成功:结果是失败的。

    尝试:重新安装php:4.4-fpm还是一样
    
    	 安装PDO,但是从phpinfo()看还是没变。
    
    未解决,同学说并不影响就先放着了。
    

    问题5:php连接mysql连接不上,查看容器运行状态发现mysql没有在运行,php连接mysql连接不上,查看容器运行状态发现mysql没有在运行。

    解决方法:使用docker logs mysql发现问题在与mysql的dockerfile中没设置root密码。在dockerfile_mysql中添加
    
    ENV MYSQL_ROOT_PASSWORD 123456
    
    ENV MYSQL_ALLOW_EMPTY_PASSWORD no
    

    问题6:解决了问题5后,访问localhost/index.php出现SQLSTATE[HY000][2002]Connection refused

    解决办法:原因是数据库没有启动
    
    service mysql start
    

    2.感想

    记录完成作业所花的时间:看资料一个早上加一个下午,实际操作一个晚上加一早上

    每次开始做这个作业之前都得深呼吸,告诉自己莫生气莫着急。当第一遍,发现phpmyadmin的dockerfile文件是空的从而导致docker-compose up停止,一切还觉得能接受能接受。然后一个晚上都在慢慢地pull phpmyadmin,心态逐渐崩塌,无数次痛锤自己为什么第一次不好好检查一下。中间无数次的docker-compose down,意志又逐渐坚强。

    很多时候其实不是不懂那个知识点,但是实操总会出错。有时候也确实是不懂那个知识点,上网查的话也不知道具体该查什么,这时候就该感谢热心解决问题的同学,解决了困扰我一早上的问题。总之还是多看多学多问。

  • 相关阅读:
    软件概要设计
    项目文件-搭建工程
    select标签中设置只读几种解决方案
    PHP ob缓冲区函数的使用
    laravel笔记
    ubuntu系统更新命令
    RBAC权限控制系统
    laravel 数据库获取值的常用方法
    php中获取数据 php://input、$_POST与$GLOBALS['HTTP_RAW_POST_DATA']三者的区别
    php 文件上传 $_FILES 错误码
  • 原文地址:https://www.cnblogs.com/huang0926huang/p/12835999.html
Copyright © 2020-2023  润新知