系统综合实践——第3次实践作业:基于Docker compose的多容器协同
本课程最终的应用需要组装多个容器提供的多个服务,Docker compose是作为定义和运行多容器的工具, 用户可以使用 YML 文件来配置应用程序需要的所有服务。
一、实践记录
1.实践问答
(1)时间记录
- 开始时间——2021/04/16 19:00
- 结束时间——2021/04/25 22:00
- 有效时长——15h
(2)难易程度
- B.比较困难
2.实验环境
- VisualBox_6.1虚拟机
- Ubuntu 18.04.5 Desktop amd64 的虚拟机系统;
【软件工具】
- nano/Text Editor
- Docker Engine-Community
- docker-hub
- aliyun镜像仓库
- Firefox浏览器
- NginX
- mysql-5.7
- PHP
- apache-tomcat-8.5.65.tar.gz
- jdk-8u211-linux-x64.tar.gz
3.实验任务
学习使用Docker compose构建相应的服务:
(1)使用Docker-compose 实现LNMP的Web服务。
(2)使用Docker-compose实现 Tomcat+Nginx负载均衡。
二、实践1——LNMP服务
Web服务需要完成,web服务器、数据库、开发程序等服务的组装,典型的如 LNMP(Linux+Nginx+Mysql+PHP)。
1.环境准备
(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 //建立同步链接
测试:
sudo docker-compose --version
(2)拉取镜像
sudo docker images
sudo docker pull php:7.4-fpm
(3)建立工作目录
cd /home/ubuntu/lancl/docker_build
mkdir compose_docker
cd /home/ubuntu/lancl/docker_build/compose_docker
mkdir web
mkdir mysql_data
2.编写配置文件
(1)Nginx:default.conf
sudo nano default.conf
server {
listen 9191; #修改映射端口
server_name localhost;
location / {
root /web/html; #修改工作目录/home/ubuntu/lancl/docker_build/compose_docker/web
index index.html index.htm; #index.html int
}
# 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$ {
root /web/php; #修改工作(代码)目录
fastcgi_pass php_container_92135:9000; #修改为容器名phpfpm
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
(2)yml文件
sudo nano docker-compose.yml
version: "3"
services:
nginx:
image: nginx_image_92135 #指定镜像名
container_name: nginx_container_92135 #指定容器名
build:
context: .
dockerfile: dockerfile_nginx #指定dockerfile文件
ports:
- "9191:9191" #修改端口映射,宿主机:容器
volumes:
- ./web:/web/html #挂载容器卷,本地/容器内修改文件后,另一方都会同步更新;
- ./default.conf:/etc/nginx/conf.d/default.conf #挂载配置文件
php:
image: php_image_92135
container_name: php_container_92135
build:
context: .
dockerfile: dockerfile_php
environment:
MYSQL_PASSWORD: 123456 #设置好环境变量,在php代码中使用变量名直接引用
volumes:
- ./web:/web/php #挂载工作目录到本机web目录
mysql:
image: mysql_image_92135
container_name: mysql_container_92135
build:
context: .
dockerfile: dockerfile_mysql
ports:
- "3306:3306"
volumes:
- ./mysql_data:/var/lib/mysql #挂载容器卷,实现数据同步,防止数据丢失
(3)Dockerfile文件
① sudo nano dockerfile_mysql
#基础镜像
FROM mysql:5.7
#镜像作者
MAINTAINER 032092135
#设置不允许免密登录并设置root密码
ENV MYSQL_ALLOW_EMPTY_PASSWORD no
ENV MYSQL_ROOT_PASSWORD=123456
② sudo nano dockerfile_nginx
#基础镜像
FROM nginx
#作者信息
MAINTAINER 032092135
#声明暴露端口
EXPOSE 9191
③ sudo nano dockerfile_php
#基础镜像
FROM php:7.4-fpm
#作者信息
MAINTAINER 032092135
#安装扩展pdo
#COPY sources.list /etc/apt
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
(4)测试文件
cd /home/ubuntu/lancl/docker_build/compose_docker/web
① sudo nano index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>032092135-lancl</title>
</head>
<body>
<h1> NGINX SUCCESS </h1>
<p>docker-compose --build successfully! </p>
<p>hello_world!!!</p>
</body>
</html>
② sudo nano index.php
<?php phpinfo();?>
(5)工作空间一览
sudo apt install tree
cd /home/ubuntu/lancl/docker_build/compose_docker
tree
3.实验过程——连接测试
(1)执行docker-compose文件
cd /home/ubuntu/lancl/docker_build/compose_docker
sudo docker-compose up -d --build //-d后台运行
(2)浏览器连接
打开浏览器,在地址栏输入:localhost:9191/index.php
localhost/index.html
localhost/index.php //- 80端口
http://localhost:9191/index.php
http://localhost:9191/index.html //- 9191端口
(3)docker-compose相关操作
需要在yml文件所在目录下执行,
sudo docker-compose ps //列出所有docker-compose容器
sudo docker-compose down //停止并删除运行中的 Compose 应用(容器和网络)
sudo docker-compose up //重新部署
sudo docker-compose stop //停止
sudo docker-compose restart //重新运行
4.实验过程——LNMP服务测试
(1)web端连接数据库服务器
修改index.php文件
<?php
$servername = "mysql_container_92135"; #用自定义的MySQL容器名
$username = "root";
$password = "123456";
try {
$conn = new PDO("mysql:host=$servername", $username, $password);
echo "连接成功!";
}
catch(PDOException $e)
{
echo $e->getMessage();
}
?>
打开浏览器,在地址栏输入:localhost:9191/index.php
(2)创建自定义数据库
sudo nano createMyDB.php
<?php
$servername = "mysql_container_92135"; #用自定义的MySQL容器名
$username = "root";
$password = "123456";
try {
$conn = new PDO("mysql:host=$servername", $username, $password);
echo "连接成功!<br>";
// 设置PDO错误模式为异常
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// sql语句
$sql0 = "DROP DATABASE myDB";
$sql = "CREATE DATABASE myDB";
// 使用 exec() ,因为没有结果返回
$conn->exec($sql0);
$conn->exec($sql);
echo "数据库myDB,创建成功!<br>";
}
catch(PDOException $e)
{
echo $sql . "<br>" . $e->getMessage();
}
$conn = null;
?>
打开浏览器,在地址栏输入:localhost:9191/createMyDB.php
进入mysql容器,再进入数据库并查询数据库myDB是否存在
格式: mysql -h主机地址 -u用户名 -p用户密码 -P端口
sudo docker exec -it mysql_container_92135 /bin/bash
mysql -u root -p //密码:123456
show databases;
use myDB
show tables;
select * from user;
exit/quit //退出数据库
exit //退出容器
(3)数据库操作
sudo nano createTable.php
<?php
$servername = "mysql_container_92135";
$username = "root";
$password = "123456";
$dbname="myDB";
try {
$conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
echo "连接成功!<br>";
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sql = "CREATE TABLE user(
id INT(8) UNSIGNED PRIMARY KEY,
name VARCHAR(30) NOT NULL,
age INT DEFAULT NULL
)";
$conn->exec($sql);
echo "user表创建成功";
}
catch(PDOException $e)
{
echo $sql . "<br>" . $e->getMessage();
}
$conn = null;
?>
sudo nano insertTable.php
<?php
$servername = "mysql_container_92135";
$username = "root";
$password = "123456";
$dbname="myDB";
try {
$conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
echo "连接成功!<br>";
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// 开始事务
$conn->beginTransaction();
// SQL 语句
$conn->exec("INSERT INTO user (id,name,age)
VALUES (032092135, 'LCL',21)");
$conn->exec("INSERT INTO user (id,name,age)
VALUES (032092133, 'GYL',22)");
$conn->exec("INSERT INTO user (id,name,age)
VALUES (032092131, 'LHH',20)");
// 提交事务
$conn->commit();
echo "新记录插入成功!";
}
catch(PDOException $e)
{
// 如果执行失败回滚
$conn->rollback();
echo $sql . "<br>" . $e->getMessage();
}
$conn = null;
?>
sudo nano deleteFromTable.php
<?php
$servername = "mysql_container_92135";
$username = "root";
$password = "123456";
$dbname="myDB";
try {
$conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
echo "连接成功!<br>";
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// 开始事务
$conn->beginTransaction();
// SQL 语句
$conn->exec("DELETE FROM user where id=032092133");
// 提交事务
$conn->commit();
echo "记录删除成功!";
}
catch(PDOException $e)
{
// 如果执行失败回滚
$conn->rollback();
echo $sql . "<br>" . $e->getMessage();
}
$conn = null;
?>
5.可视化操作——phpmyadmin
(1)拉取镜像
sudo docker pull phpmyadmin/phpmyadmin:latest
(2)修改配置文件
sudo nano dockerfile_phpmyadmin
#基础镜像
FROM phpmyadmin/phpmyadmin
#作者信息
MAINTAINER 032092135
#声明暴露的端口
EXPOSE 8080
在yml文件中添加容器映射:
phpmyadmin:
image: phpmyadmin_image_92135
container_name: phpmyadmin_container_92135
build:
context: .
dockerfile: dockerfile_phpmyadmin
ports:
- "8080:80" # phpmyadmin默认监听80
environment:
PMA_HOST: mysql_container_92135 #指定mysql服务所在的host
(3)重启容器镜像
sudo docker-compose up
sudo docker-compose restart
登录界面
- 用户:root
- 密码:123456
控制界面
- 左边数据库栏,上方图标:(小房子)主页、退出等选项;
三、实践2——Tomcat+Nginx负载均衡
- 使用Compose实现nginx代理tomcat集群,代理2个以上tomcat;
- 编写简易的html页面和jsp页面,测试验证nginx确实将请求转发到了不同的tomcat上;
1.创建文件目录,添加配置文件
cd lancl/docker_build
mkdir load_blance
cd /home/ubuntu/lancl/docker_build/load_blance
(1)创建docker-compose.yml
sudo nano docker-compose.yml
version: "3"
services:
nginx:
image: nginx_image_lb #指定容器运行的镜像。镜像名error:nginx_image_LB,lowercasse
container_name: nginx_container_LB #指定容器名
build:
context: ./nginx
dockerfile: dockerfile_nginx #指定dockerfile文件
restart: always#容器重启策略
#ports用于映射端口的标签:HOST:CONTAINER;只是指定容器(container)的端口,宿主机(host)会随机映射端口。
ports:
- "9292:9292"
#将其它容器的ip记录到本容器中:链接到其它服务中的容器。使用服务名称(同时作为别名),或者“服务名称:服务别名”.
links:
- tomcat1:tomcat1
- tomcat2:tomcat2
- tomcat3:tomcat3
volumes:
- ./webServer:/webserver
- ./nginx/nginx.conf:/etc/nginx/nginx.conf
- ./etc/localtime:/etc/localtime
depends_on: #指定依赖关系,先启用tomcat1/2,才会启用nginx
- tomcat1
- tomcat2
- tomcat3
tomcat1:
hostname: tomcat1
build: ./tomcat #指定为构建镜像上下文路径:XXX/Dockerfile 所构建的镜像
ports:
- "8051:8080"
volumes:
- ./webServer/tomcatA:/usr/local/apache-tomcat-8.5.65/webapps/ROOT
- ./etc/localtime:/etc/localtime
tomcat2:
hostname: tomcat2
build: ./tomcat
ports:
- "8052:8080"
volumes:
- ./webServer/tomcatB:/usr/local/apache-tomcat-8.5.65/webapps/ROOT
- ./etc/localtime:/etc/localtime
tomcat3:
hostname: tomcat3
build: ./tomcat
ports:
- "8053:8080"
volumes:
- ./webServer/tomcatC:/usr/local/apache-tomcat-8.5.65/webapps/ROOT
- ./etc/localtime:/etc/localtime
(2)创建etc
让docker容器使用主机系统时间(挂入/etc/localtime)
(3)创建nginx
sudo nano dockerfile_nginx
#基础镜像
FROM nginx
#作者信息
MAINTAINER 032092135
#定义工作目录
ENV WORK_PATH /etc/nginx
#定义conf文件名
ENV CONF_FILE_NAME nginx.conf
#删除原有配置文件
RUN rm $WORK_PATH/$CONF_FILE_NAME
#复制新的配置文件
COPY ./$CONF_FILE_NAME $WORK_PATH/
#给shell文件赋读权限
RUN chmod a+r $WORK_PATH/$CONF_FILE_NAME
#声明暴露端口
EXPOSE 9292
sudo nano nginx.conf
#【全局块】:配置影响nginx全局的指令。
user nginx; #配置用户/组,默认为nobody
worker_processes 1; #允许生成的进程数,默认为1
error_log /var/log/nginx/error.log warn; #制定日志路径,级别依次为:debug|info|notice|warn|error|crit|alert|emerg
pid/var/run/nginx.pid; #nginx进程pid存放路径
#【events块】:配置影响nginx服务器或与用户的网络连接。
events {
worker_connections 1024; #最大连接数,默认为512
}![](https://img2020.cnblogs.com/blog/2147268/202104/2147268-20210427221940736-1446911854.jpg)
#【http块】:可以嵌套多个server,配置代理,缓存,日志定义等绝大多数功能和第三方模块的配置。
http {
include /etc/nginx/mime.types; #文件扩展名与文件类型映射表
default_type application/octet-stream;
#自定义日志格式
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
client_max_body_size 10m; #每个进程每次调用传输数量上限
sendfile on; #允许sendfile方式传输文件,默认为off
#tcp_nopush on;
keepalive_timeout 65; #连接超时时间,默认为75s
#gzip on;
upstream tomcat_client {
server tomcat1:8080 weight=1; #1-使用weight配置负载均衡,weight默认为1,权重越高,处理请求越多
server tomcat2:8080 weight=1; #2-如果权重都是1,那么各个端口将会启用——轮询机制,8051/2/3???
server tomcat3:8080 weight=2;
}
server { #【server块】:配置虚拟主机的相关参数
server_name ""; #自定义域名host_name,localhost?
listen 9292;#修改映射端口
listen [::]:9292 ipv6only=on;
#listen 80 default_server;
#listen [::]:80 default_server ipv6only=on;
location / { #location块:配置请求的路由,以及各种页面的处理情况。
proxy_pass http://tomcat_client; #3-IP监听跳转,代理指向
proxy_redirect default;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
}
(4)创建tomcat
sudo nano Dockerfile
FROM ubuntu
ADD jdk-8u211-linux-x64.tar.gz /usr/local
ENV JAVA_HOME /usr/local/jdk1.8.0_211
ADD apache-tomcat-8.5.65.tar.gz /usr/local
EXPOSE 8080
ENTRYPOINT ["/usr/local/apache-tomcat-8.5.65/bin/catalina.sh", "run"]
apache-tomcat-8.5.65.tar.gz
jdk-8u211-linux-x64.tar.gz
- 下载
- 放到工作目录
- sudo cp /home/ubuntu/Downloads/jdk-8u211-linux-x64.tar.gz /home/ubuntu/lancl/docker_build/load_blance/tomcat
(5)创建webServer
mkdir tomcatA
mkdir tomcatB
mkdir tomcatC
cd /home/ubuntu/lancl/docker_build/load_blance/webServer/tomcatA
sudo nano index.jsp
welcome to tomcat-A server
cd tomcatB/
sudo nano index.jsp
welcome to tomcat-B server...
cd tomcatC/
sudo nano index.jsp
welcome to tomcat-C server...lalala
《Tips》
针对实践任务中遇到的各类问题和解决办法进行总结(不少于5条)。
1.实验心得
1.镜像膨胀问题?
- Dockerfile 的RUN指令每执行一次都会在 docker 上新建一层。所以过多无意义的层,会造成镜像膨胀过大。
- 以 && 符号连接命令,串联成一行,这样执行后,只会创建-1层镜像。
- 通过&&运算符,一行结束位置加上 符号,融合命令后,能够降低镜像的体积。
2.挂载test
- docker本身提供了一种机制,可以将主机上的某个目录与容器的某个目录(称为挂载点、或者叫卷)关联起来;
- 修改主机上该目录的内容时,不需要同步容器,对容器来说是立即生效的;并且,挂载点可以让多个容器共享。
- 参考:https://www.cnblogs.com/51kata/p/5266626.html
3.ports -vs - expose
- 不管是否指定主机端口,使用ports都会将端口暴露给主机。
- expose不会将端口暴露给主机。
4.配置路径混乱
-
分析:对于配置文件的语法还不够需要熟悉,需要多多查看示例文档,多多尝试。
-
dockerfile指令学习
5.sudo gedit
- open操作+/路径/文件名及后缀
- 即可利用Ubuntu自带的文本编辑器gedit进行复制粘贴快速修改文件了
6.查看端口占用
sudo netstat -anp |grep 9292
7.GitHub配置问题
sudo curl -L "https://github.com/docker/compose/releases/download/1.24.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
- 【报错:】curl: (56) OpenSSL SSL_read: SSL_ERROR_SYSCALL, errno 104
- 参考:https://www.cnblogs.com/qianshouxiuluo/p/11662616.html
2.问题记录
1.PHP连接MySQL
- pdo与mysqli有什么区别吗?