第3次实践作业
(1)完成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
然后为文件添加可执行权限
sudo chmod +x /usr/local/bin/docker-compose
创建软链
sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose
查看是否安装成功
docker-compose --version
(2)Dockerfile编写
为了保证结构的清晰明了,先创建各自的文件夹和文件,如下图所示相继创建
创建结束后文件结构如图所示
接下来为这些文件进行配置
1.html文件夹下的文件
① index.html
<h1> hello nginx </h1>
只是简单的html代码,显示hello nginx
② index.php
<?php phpinfo();?>
- 标准的php代码标签是
- phpinfo()函数会输出关于 PHP 配置的信息
2.mysql文件夹下的文件
① Dockerfile
具体解释已有注释
#基础镜像
FROM mysql:5.7
#镜像作者
MAINTAINER zzq031702223
#设置不允许免密登录并设置root密码
ENV MYSQL_ALLOW_EMPTY_PASSWORD no
ENV MYSQL_ROOT_PASSWORD=123456
② data文件夹不用配置,他是挂载的目录
3.nginx文件夹下的文件
① default.conf
具体解释已有注释
server {
listen 2223; #修改映射端口
server_name localhost;
location / {
root /www/html; # 定义服务器的默认网站根目录位置,自动生成,注意这是容器的目录,不是主机的目录
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html; # 定义错误提示页面
location = /50x.html {
root /usr/share/nginx/html;
}
location ~ \.php$ { # 通过PHP脚本到127.0.0.1:9000的FastCGI服务器监听
root /www/html; # 定义服务器的默认网站根目录位置,自动生成
fastcgi_pass php:9000; # 修改php服务器端口
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;# 修改为$document_root
include fastcgi_params;
}
}
② Dockerfile
具体解释已有注释
#基础镜像
FROM nginx:latest
#镜像作者
MAINTAINER zzq031702223
#暴露端口
EXPOSE 2223
4.php文件夹下的文件
① Dockerfile
其中更换镜像源是为了加快下载速度(没加这个之前一直报错)。
- 在php文件夹下添加sources.list即可
# 基础镜像
FROM php:7.4-fpm
# 更改镜像源
COPY sources.list /etc/apt
# 镜像作者
MAINTAINER zzq031702223
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
② sources.list
文件包含内容如下
deb https://mirrors.tuna.tsinghua.edu.cn/debian/ buster main contrib non-free
# deb-src 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-src 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-src 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
# deb-src https://mirrors.tuna.tsinghua.edu.cn/debian-security buster/updates main contrib non-free
(3)使用Compose实现多容器运行机制
1.docker-compose.yml的编写
version: "3"
services:
# nginx服务
nginx:
image: nginx_image # 镜像名
container_name: nginx_container # 容器名
build: ./nginx
ports:
- "80:2223" # 暴露端口
volumes:
- ./html:/www/html # 将主机当前目录的上级html目录,挂载到容器的/zzq/html目录
- ./nginx/default.conf:/etc/nginx/conf.d/default.conf # 同上
# php服务
php:
image: php_image
container_name: php_container
build: ./php
environment:
MYSQL_PASSWORD: 123456
volumes:
- ./html:/www/html
# mysql服务
mysql:
image: mysql_image
container_name: mysql_container
build: ./mysql
ports:
- "3306:3306"
volumes:
- ./mysql/data:/var/lib/mysql
- 值得注意的是,yml严格遵从语法规则,文本中不允许出现制表符‘\t'
2.运行docker-compose
sudo docker-compose up -d --build
3.查看容器现状
使用如下命令后,可以看见三个容器处于正常运行状态
sudo docker ps -a
(4)服务测试
1.先查看index.html和index.php能否进行访问
① index.html
访问 http://localhost/index.html
② index.php
访问 http://localhost/index.php
2.数据库测试
① 数据库的连接
修改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();
}
?>
访问 http://localhost/index.php
进行更新查看
② 数据库的创建
修改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 dockerComposeDB"; //修改数据库名
// 使用 exec() ,因为没有结果返回
$conn->exec($sql);
echo "数据库创建成功<br>";
}
catch(PDOException $e)
{
echo $sql . "<br>" . $e->getMessage();
}
$conn = null;
?>
访问 http://localhost/index.php
进行更新查看
进入容器查看数据库,以验证其正确性
③ 数据库建表
修改index.php文件如下
<?php
$servername = "mysql";
$username = "root";
$password = "123456";
$dbname="dockerComposeDB";
try {
$conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password); #选择数据库
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// 使用 sql 创建数据表
$sql = "CREATE TABLE student_list(
id int(4) not null primary key,
name varchar(16) not null
)";
// 使用 exec() ,没有结果返回
$conn->exec($sql);
echo "数据表 student_list 创建成功";
}
catch(PDOException $e)
{
echo $sql . "<br>" . $e->getMessage();
}
$conn = null;
?>
访问 http://localhost/index.php
进行更新查看
④ 插入数据
修改index.php文件如下
<?php
$servername = "mysql";
$username = "root";
$password = "123456";
$dbname="dockerComposeDB";
try {
$conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
// 设置 PDO 错误模式,用于抛出异常
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
//开始事务
$conn->beginTransaction();
$conn->exec("INSERT INTO student_list (id,name)
VALUES ('1','Tom')");
$conn->exec("INSERT INTO student_list (id,name)
VALUES ('2','Jack')");
$conn->exec("INSERT INTO student_list (id,name)
VALUES ('3','Pony')");
// 提交事务
$conn->commit();
echo "插入数据成功";
}
catch(PDOException $e)
{
$conn->rollback();
echo $sql . "<br>" . $e->getMessage();
}
$conn = null;
?>
访问 http://localhost/index.php
进行更新查看
⑤ 修改数据
修改index.php文件如下
<?php
$servername = "mysql";
$username = "root";
$password = "123456";
$dbname="dockerComposeDB";
try {
$conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
// 设置 PDO 错误模式,用于抛出异常
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
//开始事务
$conn->beginTransaction();
$conn->exec("UPDATE student_list SET id='11' WHERE name='Tom'");
// 提交事务
$conn->commit();
echo "修改数据成功";
}
catch(PDOException $e)
{
$conn->rollback();
echo $sql . "<br>" . $e->getMessage();
}
$conn = null;
?>
访问 http://localhost/index.php
进行更新查看
⑥ 删除数据
修改index.php文件如下
<?php
$servername = "mysql";
$username = "root";
$password = "123456";
$dbname="dockerComposeDB";
try {
$conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
// 设置 PDO 错误模式,用于抛出异常
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
//开始事务
$conn->beginTransaction();
$conn->exec("DELETE FROM student_list WHERE id='11'");
// 提交事务
$conn->commit();
echo "删除数据成功";
}
catch(PDOException $e)
{
$conn->rollback();
echo $sql . "<br>" . $e->getMessage();
}
$conn = null;
?>
访问 http://localhost/index.php
进行更新查看
(5)选做
1.编写相关文件
① Dockerfile文件
#基础镜像
FROM phpmyadmin/phpmyadmin
#维护者信息
MAINTAINER zzq031702223
#暴露端口
EXPOSE 8080
② 在docker-compose.yml的基础上添加相关配置
phpmyadmin:
image: phpmyadmin_image
container_name: myphpmyadmin_container
build: ./phpmyadmin
ports:
- "8080:80"
environment:
PMA_HOST: mysql
2.重新运行docker-compose
① 先停止之前运行的docker-compose
docker-compose down
② 运行docker-compose
ocker-compose up -d --build
3.数据库测试
① 先访问 localhost:8080
查看是否连接成功
② 登录并查看数据库提供的功能(建数据库)
③ 查看表
④ 插入数据
⑤ 更新数据
⑥ 删除数据
(6)实验总结
这次实验配置的文件很多,在实验过程中很容易出现错误,并且!,你根本不知道错在哪。。。
其实主要还是对知识的匮乏,不懂每个文件的具体作用,每个文件里面各行代码又是如何工作等等问题。也因为这门课内容的前沿,有些错误无法得到解答,所以实验过程还是艰难的。
由于不是很了解其中的玄妙,我尝试了使用类似访问nginx或mysql的方法来访问php,经过几个小时的磨炼,暴露nginx、mysql、php端口后,只有nginx和mysql可以被访问,而php文件始终访问失败。最终也放弃了这个想法。
大概花了八个小时才完成这次实验,挺累的。。。
继上个实验提出的问题,这次实验并没有得到解答,所以我在网上找了资料,大概了解了一些。
Linux文件系统由bootfs和rootfs两部分组成
- bootfs:包含bootloader(引导加载程序)和 kernel(内核)
- rootfs: root文件系统,包含的就是典型 Linux 系统中的/dev,/proc,/bin,/etc等标准目录和文件
- 不同的linux发行版,bootfs基本一样,而rootfs不同,如ubuntu,centos等
故而Docker镜像有如下原理
- Docker镜像是由特殊的文件系统叠加而成
- 最底端是 bootfs,并使用宿主机的bootfs
- 第二层是 root文件系统rootfs,称为base image
- 然后再往上可以叠加其他的镜像文件
- 统一文件系统(Union File System)技术能够将不同的层整合成一个文件系统,为这些层提供了一个统一的视角,这样就隐藏了多层的存在,在用户的角度看来,只存在一个文件系统。
- 一个镜像可以放在另一个镜像的上面。位于下面的镜像称为父镜像,最底部的镜像成为基础镜像。
- 当从一个镜像启动容器时,Docker会在最顶层加载一个读写文件系统作为容器
由这些知识理论,可以解答那两个问题
-
Docker 中一个centos镜像为什么只有200MB,而一个centos操作系统的iso文件要几个个G?
- Centos的iso镜像文件包含bootfs和rootfs,而docker的centos镜像复用操作系统的bootfs,只有rootfs和其他镜像层
-
Docker 中一个tomcat镜像为什么有500MB,而一个tomcat安装包只有70多MB?
- 由于docker中镜像是分层的,tomcat虽然只有70多MB,但他需要依赖于父镜像和基础镜像,所有整个对外暴露的tomcat镜像大小500多MB