系统综合实践3:基于Docker compose的多容器协同

系统综合实践——第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 的虚拟机系统;

【软件工具】

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

(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.配置路径混乱

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

2.问题记录

1.PHP连接MySQL

  • pdo与mysqli有什么区别吗?
posted @ 2021-04-27 22:21  兰小路  阅读(441)  评论(0编辑  收藏  举报