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,意志又逐渐坚强。

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

posted @ 2020-05-06 13:59  songyue  阅读(386)  评论(0编辑  收藏  举报