zoukankan      html  css  js  c++  java
  • 系统综合实践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有什么区别吗?
  • 相关阅读:
    SQLite基础-7.子句(一)
    SQLite基础-8.子句(二)
    SQLite基础-6.运算符
    SQLite基础-5.数据操作语言
    SQLite基础-4.数据定义语言(DDL)
    SQLite基础-3.语法与数据类型
    IDEA操作之FileHeager设置
    IDEA操作之test case coverage的方法
    IDEA插件之JavaDoc
    IDEA插件之JProfiler
  • 原文地址:https://www.cnblogs.com/lance-haha/p/14711139.html
Copyright © 2011-2022 走看看