docker-compose部署nodejs+eggjs+mysql+redis+nginx项目

2021-06-21 21:55 docker 2123 0
本教程将从镜像构建,容器编排,容器通信来部署实现一个基于nodejs+eggjs+mysql+nginx+react的前后端分离项目从一个小demo来从无到有搭建一个完整的项目以下所有代码均可直接访问,地址https://gitee.com/passerma/docker-node-nginx-mysql-redis一、前端界面搭建1.前端代码预览前端使用react框架搭建,具体源码请自行浏览,地址https://gitee.com/passerma/docker-node-nginx-mysql-redis/tree/master/web2.前端接口调用前端接口调用统一使用/api作为前缀,后面好通过nginx代理来访问后端服务开发时代理到http://localhost:7001package.json"proxy":"http://localhost:7001"内置登录和获取用户接口src/App.tsximportReact,{useRef,useState}from"react";import"./App.css";functionApp(){consttoken=useRef('')const[data,setdata]=useState<{id:number,userName:string}[]>([])constlogin=async()=>{constuserName='root'constpasswd='admin_123'constresponse=awaitfetch('/api/login',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({userName,passwd})});response.json().then(res=>{token.current=res.token});}constgetData=async()=>{if(!token.current){alert('请先登录!')}else{constresponse=awaitfetch('/api/list',{method:'POST',headers:{'Content-Type':'application/json','token':token.current},});response.json().then(res=>{if(res.errCode===0){setdata(res.data)}});}}return(<divclassName="App"><buttononClick={login}>登录</button><buttononClick={getData}>获取数据</button>{data.length>0&&<ul>{data.map(res=><likey={res.id}>{res.userName}</li>)}</ul>}</div>);}exportdefaultApp;其余关于数据处理即展示请查看源码二、后端代码编写1.后端代码预览后端使用eggjs框架,具体源码请自行浏览,地址https://gitee.com/passerma/docker-node-nginx-mysql-redis/tree/master/server/server2.后端接口编写后端使用eggjs框架,实现了两个接口,即登录和获取用户接口其中登录接口会将生成的token存入redis然后获取用户接口需要携带token来经redis校验获取用户数据接口如下,包含/api/login和/api/listapp\router.tsimport{Application}from'egg';exportdefault(app:Application)=>{const{controller,router}=app;router.post('/api/login',controller.home.login);router.post('/api/list',controller.home.list);};其余关于接口的编写、连接mysql数据库、读取redis和mysql的数据请查看源码3.配置文件编写配置文件主要是配置开发环境和生产环境的redis和mysql链接的1)开发环境配置使用本地的redis和mysqlconfig\config.local.tsimport{EggAppConfig,PowerPartial}from'egg';exportdefault()=>{constconfig:PowerPartial<EggAppConfig>={};config.redis={client:{port:6379,host:'127.0.0.1',password:'',db:0,},};config.mysql={client:{host:'127.0.0.1',port:'3306',user:'root',password:'admin_123',database:'test',},app:true,agent:false,};returnconfig;};2)生产环境配置使用生产环境下,使用redis镜像和mysqlconfig\config.prod.tsimport{EggAppConfig,PowerPartial}from'egg';exportdefault()=>{constconfig:PowerPartial<EggAppConfig>={};config.redis={client:{port:6379,host:'redis',password:'',db:0,},};config.mysql={client:{host:'mysql',port:'3306',user:'root',password:'admin_123',database:'test',},app:true,agent:false,};returnconfig;};其中redis的host:"redis"代表redis镜像构建的容器名其中mysql的host:"mysql"代表mysql镜像构建的容器名之后可以通过构建相同网桥的形式来使用容器名进行容器间的通信三、Dockerfile文件编写1.nginx镜像构建Dockerfile文件如下FROMnginxCOPYdefault.conf/etc/nginx/conf.d/default.confADDbuild//usr/share/nginx/build其中default.conf即为nginx的配置文件,**/etc/nginx/conf.d/**为配置文件目录/usr/share/nginx/static为静态文件目录default.confserver{listen80;listen[::]:80;server_namelocalhost;#access_log/var/log/nginx/host.access.logmain;location/api{proxy_set_headerHost$host;proxy_set_headerX-Real-IP$remote_addr;proxy_set_headerX-Forwarded-Protohttps;proxy_set_headerX-Forwarded-For$remote_addr;proxy_set_headerX-Forwarded-Host$remote_addr;proxy_passhttp://server:7001;}location/{root/usr/share/nginx/build;indexindex.htmlindex.htm;}#error_page404/404.html;#redirectservererrorpagestothestaticpage/50x.html#error_page500502503504/50x.html;location=/50x.html{root/usr/share/nginx/html;}#proxythePHPscriptstoApachelisteningon127.0.0.1:80##location~\.php${#proxy_passhttp://127.0.0.1;#}#passthePHPscriptstoFastCGIserverlisteningon127.0.0.1:9000##location~\.php${#roothtml;#fastcgi_pass127.0.0.1:9000;#fastcgi_indexindex.php;#fastcgi_paramSCRIPT_FILENAME/scripts$fastcgi_script_name;#includefastcgi_params;#}#denyaccessto.htaccessfiles,ifApache'sdocumentroot#concurswithnginx'sone##location~/\.ht{#denyall;#}}修改静态文件目录为/usr/share/nginx/build,增加代理/api到node容器的7001端口同时将打包编译的build文件拷贝到静态目录下2.nodejs和eggjs镜像构建Dockerfile文件如下FROMalpineADDserver//usr/local/node-serverWORKDIR/usr/local/node-serverRUNapkaddnodejsnpm&&npminstall-gcnpm--registry=https://registry.npm.taobao.org&&cnpmi&&npmruntscCMD["npm","start"]由于官方的node镜像十分之大,因此这里我们通过alpine来构建一个nodejs环境同时我们将后台相关文件放在server文件,并拷贝至镜像/usr/local/node-server目录下然后设置npmstart为容器启动时的命令3.mysql镜像构建Dockerfile文件如下FROMmysql:5.7COPYcreate_table.sql/docker-entrypoint-initdb.d我们在启动MySQL容器时自动创建我们需要的数据库和表对应的sql文件为create_table.sql,并移动到容器/docker-entrypoint-initdb.d下create_table.sqlCREATEDATABASEIFNOTEXISTS`test`;USE`test`;CREATETABLEIFNOTEXISTS`users`(`id`INT(11)UNSIGNEDAUTO_INCREMENT,`userName`VARCHAR(255)NOTNULL,PRIMARYKEY(`id`))ENGINE=InnoDBDEFAULTCHARSET=utf8mb4COLLATE=utf8mb4_unicode_ci;mysql官方镜像中提供了容器启动时自动docker-entrypoint-initdb.d下的脚本的功能4.redis镜像构建redis使用默认的官方镜像即可四、docker-compose实现容器编排1.整理目录结构在使用容器编排前,需要先整理下我们的目录结构web-----前端项目文件,与docker-compose无关,仅用于生成build里的静态文件mysql------Dockefilemysql镜像的Dockefile文件nginx------Dockefilenginx镜像的Dockefile文件------build前端打包后的静态文件server-----Dockefilenode环境及后台服务镜像的Dockefile文件-----servereggjs文件目录,提供后台服务docker-compose.ymldocker-compose的配置文件2.安装docker-compose下载docker-composesudocurl-L"https://github.com/docker/compose/releases/download/1.24.1/docker-compose-$(uname-s)-$(uname-m)"-o/usr/local/bin/docker-compose设置docker-compose执行权限sudochmod+x/usr/local/bin/docker-compose创建软链sudoln-s/usr/local/bin/docker-compose/usr/bin/docker-compose测试是否安装成功:docker-compose--versioncker-composeversion1.24.1,build4667896b3.编写docker-compose.yml文件完整的docker-compose.yml文件如下其中配置文件详解如下docker-compose.ymlversion:"3.0"services:redis:container_name:redisimage:redisports:-"6379:6379"restart:on-failurenetworks:-my-servermysql:container_name:mysqlbuild:context:mysqldockerfile:Dockerfileports:-"3306:3306"restart:on-failureenvironment:-MYSQL_ROOT_PASSWORD=admin_123networks:-my-serverserver:container_name:serverbuild:context:serverdockerfile:Dockerfileports:-"7001:7001"restart:on-failurenetworks:-my-serverdepends_on:-redis-mysqlnginx:container_name:nginxbuild:context:nginxdockerfile:Dockerfileports:-"80:80"restart:on-failurenetworks:-my-serverdepends_on:-redis-mysql-servernetworks:my-server:server中的redis为官方镜像,直接启动即可,同时设置自动重启使用专属网桥my-serverserver中的mysql为自己编译的mysql镜像其中MYSQL_ROOT_PASSWORD为root的用户密码,需设置与mysql配置文件里的一致build里指定了Dockerfile目录使用专属网桥my-serverserver中的server为自己编译的nodejs服务镜像build里指定了Dockerfile目录使用专属网桥my-servernode服务依赖于mysql和redis同时设置自动重启,这一步必须设置,主要是存在mysql还没有启动完成就启动了node服务会导致后台服务无法启动从而退出,这时再重启直到连接数据库成功为止server中的nginx为自己编译的前端服务镜像build里指定了Dockerfile目录使用专属网桥my-server同时设置自动重启,这一步必须设置,主要是存在node还没有启动完成就启动了nginx服务会导致连接不上node的host而退出,这时再重启直到代理到node地址成功为止最后声明一下网桥my-server将所有服务都挂载在同一网桥即可通过容器名来互相通信了至此docker-compose配置文件编写完成,直接后台启动即可docker-composeup-d启动完成,查看容器是否都正常运行输入宿主机ip查看界面点击登录,然后点击获取数据,流程畅通这时我们可以通过宿主机ip:3306连接数据库,在users表添加几条数据再次点击获取数据,可以查询到刚添加的记录五、总结至此,整个项目的环境就搭建完成了,不过还是有许多需要优化的地方,比如通过shell脚本来控制数据库完全启动再启动node服务,而不是一直重启node直到连接上为止之后只需要一步步完善整个流程即可实现更为复杂的项目
暂无评论,我会出手
说点什么
登录用户可以修改和删除评论,可以收到回复的邮件提醒点击登录/注册
最多上传8张图片,仅支持jpg,png格式图片,单张大小5MB以内!
用户名: