docker+compose在内部搭建应用及测试环境中的应用

概要

使用docker很久了,以前只是在单台服务器中安装docker,分别启动公司内部的管理系统,解决服务器资源利用率不高及端口之间相互冲突问题。

此次入职新公司,发现公司内部需要处理更复杂的问题,公司内部实体服务器目前有两台,除了安装必要的git、svn、redmine、jenkins等内部开发管理系统外,还要部署多个客户的测试环境,应用多以虚拟机方式部署,耗费太多额外资源,导致服务器很慢。同时,由于产品特性,单一客户测试环境需要部署nginx、mysql、redis、sftp、tomcat等众多应用,这就造成单个tomcat下会部署多个工程,这些工程除了访问端口外,还开了dubbo、websocket等端口,为了防止端口冲突,每次部署都需要根据客户单独修改端口,过程错综复杂,难免发生开发意外的错误导致研发费时费力地去处理。为了处理这些问题,根据以往经验、经讨论后决定使用docker代理实例服务器。

实施方案

由于内部两台服务器不好随便动,因此借助另外一台PC机作为过渡,具体计划如下(为了方便理解,下文的服务器按如下编号:server1、server2、PC1):

1、PC1容器化

      安装centos7并容器化

2、测试环境容器化

      将测试环境server2迁移到PC1的容器中

3、server2容器化

     server2安装centos7并容器化

4、迁移开发管理系统

       将内部开发管理系统server1迁移到server2的容器中

5、server1容器化

      server1安装centos7并容器化

6、迁移测试环境(可不迁移,放在PC1,看后续性能)

     将PC1的容器迁移到server1(PC1后续可能会加入,组成容器集群)

实施

本次先介绍到第二步,测试环境容器化,其他类似此处不再累述。

一、PC1容器化

需要安装docker、webmin(管理linux系统用)

1、PC1安装centos7(具体百度)

2、安装webmin

1)下载webmin
http://www.webmin.com/download.html
2)安装perl依赖
yum -y install perl perl-Net-SSLeay openssl perl-IO-Tty perl-Encode-Detect perl-Data-Dumper
3)安装webmin
rpm -Uvh webmin-1.910-1.noarch.rpm
4)设置开机启动
文件中:/etc/rc.d/rc.local
加入:/etc/webmin/start
5)访问webmin
https://localhost.localdomain:10000/init/?xnavigation=1

3、PC1安装docker

参考:https://docs.docker.com/install/linux/docker-ce/centos/

1)升级依赖集配置仓库地址

yum install -y yum-utils device-mapper-persistent-data lvm2
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo

2)安装docker-ce(开源版本)

yum install docker-ce docker-ce-cli containerd.io

3)通过webmin设置docker开机启动并启动docker

docker+compose在内部搭建应用及测试环境中的应用_第1张图片

docker+compose在内部搭建应用及测试环境中的应用_第2张图片

4、PC1安装compose

参考:https://docs.docker.com/compose/install/

1)下载compose

sudo curl -L "https://github.com/docker/compose/releases/download/1.24.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

2)设置执行权限

sudo chmod +x /usr/local/bin/docker-compose

二、测试环境容器化

测试环境涉及以下组件:mysql、redis、sftp、nginx、tomcat等,我们在规划compose时,设计为2组:一为公共组件,mysql、redis、sftp,这部分所有客户共享,资源不存在冲突,后续如果用户使用率高了,课考虑私有化;另一个为私有组件,nginx、tomcat,用于部署客户应用,客户应用分为三部分:page、api和service,page为vue编辑纯前端页面,api为对外公开的接口服务,采用springmvc,service为系统核心服务,使用dubbo和api层通信,系统业务架构如下:

docker+compose在内部搭建应用及测试环境中的应用_第3张图片

部署架构为:

docker+compose在内部搭建应用及测试环境中的应用_第4张图片

1、公共组件

公共组件使用common_default网络,同时对host组件暴露端口:mysql 3306、redis 6379、sftp 4023,compose.yml如下:

version: "3"
services:
  mysql:
    image: mysql
    volumes:
      - /opt/docker-common/mysql/data:/var/lib/mysql
      - /opt/docker-common/mysql/logs:/var/log/mysql
    ports:
      - "3306:3306"
    environment:
        MYSQL_ROOT_PASSWORD: "Longer.1234"
        lower_case_table_names: "1"
        TZ: Asia/Shanghai
    command: --lower_case_table_names=1
    container_name: mysql
    networks:
      - default
      
  redis:
    image: redis
    ports:
      - "6379:6379"
    environment:
       TZ: Asia/Shanghai
    command: redis-server --requirepass longer
    container_name: redis
    networks:
      - default
    
  sftp:
    image: atmoz/sftp
    volumes:
      - /opt/docker-common/sftp:/home
    environment:
       TZ: Asia/Shanghai
    ports:
      - "4023:22"
    command: mysftp:mysftp.1234:::mysftp
    container_name: sftp
    networks:
      - default
    
networks: ##定义网络组
    default:

启动docker之前按照compose.yml建立文件目录,然后启动docker:

docker-compose up -d

2、私有组件

私有组件为客户测试环境,启动一个nginx负责前端网站和反向代理;三个tomcat,一个api,两个service负责服务,通过nginx做负载均衡。

version: "3"
services:
  nginx: # 服务的名称
    image: nginx
    volumes: # 文件夹映射
      - /opt/${customer_code}/nginx/html:/usr/share/nginx/html # 宿主:docker:只读  ,www目录
      - /opt/${customer_code}/nginx/conf/nginx.conf:/etc/nginx/nginx.conf # nginx配置文件
      - /opt/${customer_code}/nginx/conf/conf.d:/etc/nginx/conf.d # nginx配置文件
      - /opt/${customer_code}/logs/nginx:/var/log/nginx  #日志
      - /opt/docker-common/sftp:/var/sftp
    environment:
       TZ: Asia/Shanghai
    ports: # 端口转发 宿主:docker
      - "${web_port}:80"
    expose:
      - "80"
      - "20887"
    depends_on:
      - web1
      - web2
      - api1
    container_name: ${customer_code}-nginx
    networks:
      default:
         aliases:
          - container_nginx

  web1:
    image: tomcat
    volumes:
      - /opt/${customer_code}/web:/usr/local/tomcat/webapps
      - /opt/${customer_code}/logs/web1:/usr/local/tomcat/logs
      - /opt/${customer_code}/tmp:/home/test
    environment:
       JAVA_OPTS: -Dsupplements.host=supplements
       CATALINA_OPTS: -server -Xms256M -Xmx1024M -XX:MaxNewSize=256m -XX:PermSize=64M -XX:MaxPermSize=256m
       TZ: Asia/Shanghai
    expose:
      - "8080"
      - "20887"
    external_links:
      - mysql
      - redis
      - sftp
    container_name: ${customer_code}-web1
    networks:
      default:
         aliases:
          - container_web1
      docker-common_default:
    
  web2:
    image: tomcat
    volumes:
      - /opt/${customer_code}/web:/usr/local/tomcat/webapps
      - /opt/${customer_code}/logs/web2:/usr/local/tomcat/logs
      - /opt/${customer_code}/tmp:/home/test
    environment:
       JAVA_OPTS: -Dsupplements.host=supplements
       CATALINA_OPTS: -server -Xms256M -Xmx1024M -XX:MaxNewSize=256m -XX:PermSize=64M -XX:MaxPermSize=256m
       TZ: Asia/Shanghai
    expose:
      - "8080"
      - "20887"
    external_links:
      - mysql
      - redis
      - sftp
    container_name: ${customer_code}-web2
    networks:
      default:
         aliases:
          - container_web2
      docker-common_default:

  api1:
    image: tomcat
    volumes:
      - /opt/${customer_code}/api:/usr/local/tomcat/webapps
      - /opt/${customer_code}/logs/api1:/usr/local/tomcat/logs
    environment:
       JAVA_OPTS: -Dsupplements.host=supplements
       CATALINA_OPTS: -server -Xms256M -Xmx1024M -XX:MaxNewSize=256m -XX:PermSize=64M -XX:MaxPermSize=256m
       TZ: Asia/Shanghai
    expose:
      - "8080"
    depends_on:
      - web1
    external_links:
      - mysql
      - redis
      - sftp
    container_name: ${customer_code}-api1
    networks:
      default:
         aliases:
          - container_api1
      docker-common_default:

networks: ##定义网络组
  default:
  docker-common_default:
   external: true
   

按照compose.yml建立文件目录并配置nginx:

nginx.conf


#user  nobody;
user  root;
worker_processes  1;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include       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  logs/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    #gzip  on;
	gzip  on;
    gzip_min_length 1k;
    gzip_buffers 4 16k;
    gzip_http_version 1.0;
    gzip_comp_level 6;
    gzip_types application/javascript application/x-javascript application/json application/font-woff text/plain text/javascript text/xml text/css image/jpeg image/jpg image/gif image/png;
    gzip_disable "MSIE [1-6]\.";
    gzip_vary on;
	include       conf.d/*.conf;
}
stream {
    log_format proxy '$remote_addr [$time_local] '
                 '$protocol $status $bytes_sent $bytes_received '
                 '$session_time "$upstream_addr" '
                 '"$upstream_bytes_sent" "$upstream_bytes_received" "$upstream_connect_time"';
	access_log /var/log/nginx/tcp_access.log proxy;
    error_log /var/log/nginx/tcp_serror.log;
	
	include       conf.d/*.tcp;
}

app.conf

upstream container-service{
    server container_web1:8080;       #server1
    server container_web2:8080;       #server1
}
upstream container-api {
    server container_api1:8080;       #server1
}

server {
	listen       80;
	client_max_body_size     20m;
	# server_name  somename  alias  another.alias;

	location / {
		root   /usr/share/nginx/html;
		index  index.html index.htm;
	}
	location /api {
		proxy_pass http://container-api/api;
		proxy_http_version 1.1;
		proxy_set_header Upgrade $http_upgrade;
		proxy_set_header Connection "upgrade";
	}
	location /service{
		proxy_pass http://container-service/service;
		proxy_http_version 1.1;
		proxy_set_header Upgrade $http_upgrade;
		proxy_set_header Connection "upgrade";
	}
	add_header Cache-Control no-store;
	add_header Pragma: no-cache;
}

app.tcp

upstream container_dubbo{
	# hash $remote_addr consistent;
	server container_web1:20888;
	server container_web2:20888;
}

server {
	listen 20888;
	# listen 1008 udp; 通过后面添加udp,可以进行udp的转发
	proxy_connect_timeout 10s;
    proxy_timeout 30s;
    proxy_pass container_dubbo;
}

3、设置启动和停止命令

start.sh:

#!/bin/bash
export customer_code=${PWD##*/} #默认当前父目录作为客户code
export web_port=8010
docker-compose up -d

stop.sh

#!/bin/bash
export customer_code=${PWD##*/}  #默认当前父目录作为客户code
export web_port=8010
docker-compose stop

后启动客户测试环境:

./start.sh

4、验证结果

查看容器实例:

docker ps

编写一个html文件,名称为index.html,放到nginx/html目录下

访问:http://hostip:8010

查看效果

后记

至此,一个PC容器化并搭建完整测试环境的过程已经介绍完,下面整理下整个过程中遇到的坑,供各位参考。

1、不同网络间容器引用、通信问题(external_links)

一开始的公共组件不是使用compose启动,而是通过docker直接启动,使用docker默认的网络bridge,在私有组件访问公共组件配置过程中,配置私有组件compose.yml、使用external_links参数配置的外部mysql等组件,一直不能实现互相连接,期间通过networks参数引入bridge,将私有组件加入该网络也不行,后来通过另外建立新的网络,不用默认的bridge解决问题,在此期间多次查阅官方文档,未能找出原因,后续只能人为规避使用默认的docker网络。

你可能感兴趣的:(架构,dcoker,项目管理,compose)