使用docker构建并测试一个基于Sinatra的Web应用程序
内容来自《第一本Docker书》5.2节和博文整理而成
使用Docker构建并测试Web应用程序
在这个例子里,我们将创建一个应用程序,它接收输入的URL参数,并以JSON散列的结构输出到客户端。通过这个例子,我们也将展示一下如何将Docker容器链接起来。
1.构建Sinatra应用程序
- 在sinatra目录下创建一个webapp目录,这个目录作为Sinatra Web应用程序的根目录
cd sinatra
mkdir webapp
ls
- 在webapp目录下创建一个lib目录,然后在lib目录中创建一个app.rb文件作为Sinatra Web程序的源码
mkdir webapp/lib
touch webapp/lib/app.rb
在webapp目录下创建一个bin目录,然后在bin目录中创建一个webapp可执行文件,这个可执行文件就是用来启动Sinatra服务的,其源码为上面的app.rb。为了可以启动webapp,给其增加可执行权限
mkdir webapp/bin
touch webapp/bin/webapp
chmod +x webapp/bin/webapp
vim webapp/lib/app.rb
webapp/lib/app.rb的内容如下:
- 这个文件是Sinatra Web程序的源码
- 可以看到这个程序很简单,客户端如果以/json结尾的URL去访问sinatra Web服务(POST请求),那么服务端会将请求以JSON的格式返回给客户端
require "rubygems"
require "sinatra"
require "json"class App < Sinatra::Applicationset :bind, '0.0.0.0'get '/' do"<h1>DockerBook Test Sinatra app</h1>"endpost '/json/?' doparams.to_jsonendend
编辑webapp文件
vim webapp/bin/webapp
webapp文件,内容如下:
- 用来启动Sinatra Web程序的
- 需要可执行权限
#!/usr/bin/ruby$:.unshift(File.expand_path(File.join(File.dirname(__FILE__), "..", "lib")))require 'app'App.run!
现在目录的结构如下:
3. 在webapp目录下创建一个Dockerfile文件,待会用来构建镜像的
touch webapp/Dockerfile
vim webapp/Dockerfile
Dockerfile的内容如下:
- FROM指令:构建该镜像的基础镜像
- MAINTAINER指令:该镜像的作者和邮箱
- ENV指令:为了重新构建缓存
- 第1、2条RUN指令:换阿里源
- 第3条RUN指令:更新源,并安装Ruby和RubyGem
- 第4条RUN指令:安装sinatra(Sinatra的库)、json(提供对JSON的支持)、redis、gem(后面会用到,用来和Redis数据库进行集成)
- 第5条RUN指令:创建一个目录,作为本次Sinatra Web运行环境的根环境目录
- EXPOSE指令:公开该容器的4567端口。sinatra的默认端口为4567,所以下面启动sinatra服务的时候需要把这个端口开放出来
- CMD指令:该指令用来执行一条shell命令,此处为执行/opt/webapp/bin/目录下的webapp应用程序,也就是在镜像内运行sinatra Web应用程序
FROM ubuntu:16.04
MAINTAINER cws "634068240@qq.com"
ENV REFRESHED_AT 2021-04-28
RUN sed -i s@/archive.ubuntu.com/@/mirrors.aliyun.com/@g /etc/apt/sources.list
RUN apt-get clean
RUN apt-get -yqq update && apt-get -yqq install ruby ruby-dev build-essential redis-tools
RUN gem install --no-rdoc --no-ri sinatra json redis
RUN mkdir -p /opt/webapp
EXPOSE 4567
CMD [ "/opt/webapp/bin/webapp" ]
- 基于Dockerfile构建镜像
- 在sinatra目录下,输入下面的命令构建镜像:
- 镜像的名字为cws/sinatra
- 使用到的Dockerfile文件位于./webapp目录下
docker build -t cws/sinatra ./webapp
2.创建Sinatra容器
- 基于创建的镜像启动Docker容器
- 上面我们已经成功的创建镜像了,现在可以输入下面的命令来创建一个容器(备注:要在sinatra目录下执行这条命令):
- -d:将容器以守护进程的模式在宿主机中运行
- -p:将容器的4567端口映射到任意一个宿主机的端口上
- –name:将容器命名为webapp
- -v:
- 将宿主机的目录作为卷,挂在到容器中。
- 此处我们将宿主机当前路径($PWD)下的webapp目录挂载到容器的/opt/webapp目录下,上面我们的Dockerfile文件已经介绍了,容器的/opt/webapp会作为sinatra Web服务的根环境目录
- 也就是说,访问/opt/webapp下的内容就会访问到宿主机当前路径下的webapp目录
- 最后一个选项为镜像的名称cws/sinatra
docker run -d -p 4567 --name webapp -v $PWD/webapp:/opt/webapp cws/sinatra
看一下容器的4567端口映射到当前宿主机的哪个端口上
docker port webapp 4567
通过命令测试sinatra服务: 上面我们介绍过,如果客户端的请求是以/json结尾的,那么sinatra web程序会将请求参数以JSON的形式返回给客户端,现在我们可以通过curl来测试,可以看到我们在URL中输入了name和status,sinatra以JSON的形式返回给我们了
curl -i -H 'Accept: application/json' -d 'name=Foo&status=Bar' http://localhost:49273/json
3.扩展Sinatra应用程序来使用Redis
上面我们已经搭建好了一个含有Sinatra Web服务的Docker,名为cws/sinatra
现在我们需要为Sinatra Web服务加入一个Redis后端数据库,并在Redis数据库中存储客户端的URL参数
此处我们重新构建一个镜像,在里面只运行redis服务端,与之前的容器是相互独立的
创建目录、文件
在sinatra目录下 创建一个redis目录,然后再里面创建一个Dockerfile文件
mkdir redis
touch redis/Dockerfile
Dockerfile文件的内容如下:
- FROM指令:构建该镜像的基础镜像
- MAINTAINER指令:该镜像的作者和邮箱
- ENV指令:为了重新构建缓存
- RUN指令:更新源,并安装redis服务器和工具
- EXPOSE指令:公开该容器的6379端口。因为redis服务端的默认端口为6379
- ENTRYPOINT指令:与CMD类似,用来执行一条命令。此处我们为启动redis的服务端程
FROM ubuntu:16.04
MAINTAINER cws "634068240@qq.com"
ENV REFRESHED_AT 2021-04-28
RUN sed -i s@/archive.ubuntu.com/@/mirrors.aliyun.com/@g /etc/apt/sources.list
RUN apt-get clean
RUN apt-get -yqq update && apt-get -yqq install redis-server redis-tools
EXPOSE 6379
ENTRYPOINT ["/usr/bin/redis-server" ]
CMD []
现在目录结构为:
构建镜像、创建容器
输入下面的命令,根据上面的Dockerfile文件构建一个名为cws/redis的镜像
docker build -t cws/redis ./redis
基于上面的镜像来创建一个Docker容器,在sinatra文件下执行命令如下:
- -d:将容器以守护进程的模式在宿主机中运行
- -p:将容器的6379端口映射到任意一个宿主机的端口上
- –name:将容器命名为redis
- 最后一个选项为镜像的名称
docker run -d -p 6379 --name redis cws/redis
测试连接容器中的redis服务
查看一下redis容器的6379端口映射到了宿主机的哪个端口,如下所示:
docker port redis 6379
redis容器的6379端口映射到了宿主机的49274端口上,因此下面我们使用redis-cli客户端工具去连接:
新建目录
在sinatra目录下创建一个webapp_redis,用来作为包含redis服务的sinatra web服务端根目录
mkdir webapp_redis
再在webapp_redis目录下创建一个bin目录,在目录内创建一个webapp文件,作为sinatra服务端程序,并赋予其可执行权限
mkdir webapp_redis/bin
touch webapp_redis/bin/webapp
chmod +x webapp_redis/bin/webapp
再在webapp_redis目录下创建一个lib目录,在目录内创建一个app.rb源文件,该文件为webapp的服务端源码
mkdir webapp_redis/lib
touch webapp_redis/lib/app.rb
编辑webapp文件,webapp的内容如下:
#!/usr/bin/ruby$:.unshift(File.expand_path(File.join(File.dirname(__FILE__), "..", "lib")))require 'app'App.run!
- 编辑app.rb文件,app.rb的内容如下:
- 该文件的内容与当初的app.rb文件的功能是差不多的,在之后的app.rb的基础上增加了一个连接redis数据库的功能
- sinatra服务端连接一个名为“db”的主机上的Redis数据库,端口为6379
- 然后当接收到客户端POST请求时,将URL参数保存到Redis数据库中,并在需要的时候通过GET请求从中取回这个值
vim webapp_redis/lib/app.rb
require "rubygems"
require "sinatra"
require "json"
require "redis"class App < Sinatra::Applicationredis = Redis.new(:host => 'db', :port => '6379')set :bind, '0.0.0.0'get '/' do"<h1>DockerBook Test Redis-enabled Sinatra app</h1>"endget '/json' doparams = redis.get "params"params.to_jsonendpost '/json/?' doredis.set "params", [params].to_jsonparams.to_jsonend
end
创建Dockerfile
touch webapp_redis/Dockerfile
现在整体项目的结构如下:
编辑Dockerfile文件,内容与最初那个Dockerfile文件的内容是一模一样的
vim webapp/Dockerfile
FROM ubuntu:16.04
MAINTAINER cws "634068240@qq.com"
ENV REFRESHED_AT 2021-04-28
RUN sed -i s@/archive.ubuntu.com/@/mirrors.aliyun.com/@g /etc/apt/sources.list
RUN apt-get clean
RUN apt-get -yqq update && apt-get -yqq install ruby ruby-dev build-essential redis-tools
RUN gem install --no-rdoc --no-ri sinatra json redis
RUN mkdir -p /opt/webapp
EXPOSE 4567
CMD [ "/opt/webapp/bin/webapp" ]
基于Dockerfile构建镜像
- 在sinatra目录下,输入下面的命令构建镜像:
- 镜像的名字为cws/sinatra_redis
- 使用到的Dockerfile文件位于./webapp_redis目录下
docker build -t dongshao/sinatra_redis ./webapp_redis
基于创建的镜像启动Docker容器
创建一个容器(备注:要在sinatra目录下执行这条命令)
sudo docker run -d -p 4567 --name webapp_redis -v $PWD/webapp_redis:/opt/webapp dongshao/sinatra_redis
4.将Sinatra应用程序连接到Redis容器
现在我们需要将redis容器与webapp_redis容器相关联:
Docker有3种网络通信方式:
- ①Docker的内部网络
- ②Docker Networking功能(本文介绍)
- ③Docker链接
将之前创建的新容器都删除(并非删除镜像),下面都重新运行新容器
# 列出当前宿主机中运行的容器
sudo docker ps
# 列出当前宿主机中所有的容器
sudo docker ps -a
# 先暂停运行的容器下面才可以删除
sudo docker stop webapp_redis redis webapp
# 删除容器
sudo docker rm webapp_redis redis webapp
# 再次查看,删除成功
sudo docker ps -a
创建新的Docker网络
sudo docker network create app
docker network inspect app
启动redis容器,并加入到app新网络
- 上面我们已经成功的创建了一个名为app的网络,现在我们将redis容器加入到这个新网络中
- 命令如下,就是在运行的时候将容器加入app网络中:
- -d:将容器以守护进程的方式在宿主机中运行
- –net:指定了这个新容器运行在哪个网络中,此处为我们上面创建的那个app网络
- –name:容器的名字叫db
- 最后一个选项:镜像的名称
docker run -d --net=app --name db cws/redis
再次输入下面的命令来查看app网络的信息,如下所示:
可以看到在这个网络下新增了一个容器,其有Mac、IP等地址,IP地址为172.20.0.2
启动webapp_redis容器,并加入到app新网络
现在我们来启动webapp_redis容器,这个容器包含带有连接redis服务端的sinatra Web服务
在sinatra目录(注意)下,输入下面的命令启动webapp_redis容器:
sudo docker run -p 4567 --net=app --name webapp_redis -t -i -v $PWD/webapp_redis:/opt/webapp cws/sinatra_redis /bin/bash
我们在宿主机中输入下面的命令来查看app网络的信息:
sudo docker inspect app
对Sinatra Web服务进行验证
上面我们只是启动了sinatra_redis容器,但是没有运行里面的webapp
我们在sinatra_redis容器内执行下面的命令,启动sinatra_redis容器中的Sinatra Web服务,并且最后使用“&”符号,让其在后台运行:
nohup /opt/webapp/bin/webapp &
- 服务启动之后,在宿主机中查看一下sinatra_redis容器的4567端口映射到了当前宿主机的哪个端口上,如下图所示:
- sinatra服务的默认端口为4567
- 容器的4567端口映射到了宿主机的49277端口上
- 我们可以在网页中尝试访问这个Web服务
- 可以尝试发送POST请求:
我们的sinatra Web服务可以接受以/json结尾的POST请求,并将客户端的请求参数存放到其连接的redis容器的redis数据库中
下面我们发送了一个POST请求,并发送了两个请求参数“name”和“status”
sinatra会将POST请求的信息保存到redis数据库,并以JSON的形式再返回给客户端
curl -i -H 'Accept: application/json' -d 'name=Foo&status=Bar' http://localhost:49277/json
- 查看Redis数据库的内容:
因为sinatra会将数据存放到其连接的redis容器的redis数据库中
我们可以根据Docker的“内部网络”特性,让宿主机直接通过私有地址连接redis容器(IP为172.20.0.2)
连接上之后查看里面的数据,可以看到服务端成功的保存了数据到params键中
curl -i http://localhost:49277/json
使用docker构建并测试一个基于Sinatra的Web应用程序相关推荐
- 一个基于J2EE的web应用程序运行起来需要什么?
2019独角兽企业重金招聘Python工程师标准>>> Eclipse ?IDEA?这是目前市面上最常用的开发工具啦,我的理解是这些只是开发工具,是为了方便开发的,而不是web应用程 ...
- 使用Docker构建并测试web应用程序
使用Docker构建并测试web应用程序 构建Sinatra应用程序 构建Dockerfile FROM ubuntu:lastest MAINTAINER James Turnbull james@ ...
- java 插桩 工具_一个基于Eclipse的通用Java程序插桩工具.pdf
第38卷第7期 计算机科学 V01.38NO.7 Science 2011 2011年7月 Computer July 一个基于Eclipse的通用Java程序插桩工具 郑晓梅 (南京中医药大学信息技 ...
- AVR单片机计算器C语言源程序,一个基于AVR单片机的计算器程序.doc
一个基于AVR单片机的计算器程序 #include #include//延时函数的头文件 #include // 中断函数的头文件 #define uint unsigned int #define ...
- 一个非常轻巧的基于Groovy的Web应用程序项目模板
一个非常轻巧的基于Groovy的Web应用程序项目模板 您可能听说过该项目Grails是Ruby on Rails之类的Groovy版本的框架,该框架使您可以通过动态脚本轻松地创建Web应用程序. 尽 ...
- groovy 模板_一个非常轻巧的基于Groovy的Web应用程序项目模板
groovy 模板 一个非常轻巧的基于Groovy的Web应用程序项目模板 您可能听说过该项目Grails是Ruby on Rails之类的Groovy版本的框架,该框架使您可以通过动态脚本更轻松地创 ...
- 属于服务器端运行的程序_Telerik UI for ASP.NET MVC:为任何设备以两倍的速度构建功能丰富且响应迅速的web应用程序...
Telerik UI for ASP.NET MVC 为任何设备以两倍的速度构建功能丰富且响应迅速的web应用程序.由Kendo UI提供支持 主要功能 适用于任何应用场景的UI框架 享受满足各种需求 ...
- spring_在基于Spring的Web应用程序中使用Http Session
spring 在基于Spring的Web应用程序中拥有和使用Http会话有多种方法. 这是基于最近项目经验的总结. 方法1 只需在需要的HttpSession中注入即可. @Service publi ...
- 在Autodesk应用程序商店发布基于浏览器的Web应用程序
你一定已经听说过Autodesk应用程序商店了,通过Autodesk应用程序商店,你可以免费下载或购买来自全球的优秀开发者发布的应用程序,来帮助你更快更方便的完成你的工作.而且作为开发者,您也可以在A ...
最新文章
- linux ubuntu安装 mono,在Ubuntu 18.04系统中安装Mono及基本使用Mono的方法
- 在Windows下,用Hexo搭建博客
- Ubuntu 16.04 LTS 下安装PyCharm
- SecureCRT SSH 语法高亮
- Parallels Desktop虚拟机无法关机提示“虚拟机处理器已被操作系统重置”
- PAT乙级(1020 月饼)
- 考研计算机网络,2020计算机专业考研的计算机网络部分知识点
- ONVIF流媒体播放流程
- 6688常见问题FAQ
- 计算机单位厘米 像素,英尺和厘米的换算计算器 显示器的像素解析度可能不是...
- VIN码/车架号的详解,车架号识别,VIN码识别,OCR车架号识别能带来什么
- CodeWarrior IDE烧写介绍
- 简单的网站全屏背景图代码
- oracle remap schema,impdp的remap_schema选项的另一个schema是否要重建
- 全球首位亿万富豪上太空!
- 这四十年来的香港歌坛在唱些什么,“南中国听歌最多”的数据分析师带你一探究竟...
- Java 接口的定义、接口的成语、接口的实现、接口与类的多继承、JDK1.8后新增方法、使用接口的注意事项
- 爱普生photo EX3打印机四个灯同时闪的解决方法
- RabbitMq消息队列进一步认识
- 反相畴的基础知识和一篇论文
热门文章
- Spring 中的编程思想总结
- 项目中applicaiton.yml配置文件详细讲解
- 搭建项目前端页面环境
- 注解IOC案例-把自己编写的类使用注解配置
- ES6新特性之扩展运算符
- hystrix-dashboard
- SpringBoot_web开发-SpringMVC自动配置原理
- android和web api接口,WebService和Webapi的区别
- mysql 界面 创建用户名和密码是什么_PLSQL操作Oracle创建用户和表(含创建用户名和密码)...
- Java:ThreadPoolExecutor解析续--Executors