内容来自《第一本Docker书》5.2节和博文整理而成

使用Docker构建并测试Web应用程序

在这个例子里,我们将创建一个应用程序,它接收输入的URL参数,并以JSON散列的结构输出到客户端。通过这个例子,我们也将展示一下如何将Docker容器链接起来。

1.构建Sinatra应用程序

  1. 在sinatra目录下创建一个webapp目录,这个目录作为Sinatra Web应用程序的根目录
cd sinatra
mkdir webapp
ls
  1. 在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" ]
  1. 基于Dockerfile构建镜像
  • 在sinatra目录下,输入下面的命令构建镜像:
  • 镜像的名字为cws/sinatra
  • 使用到的Dockerfile文件位于./webapp目录下
docker build -t cws/sinatra ./webapp

2.创建Sinatra容器

  1. 基于创建的镜像启动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应用程序相关推荐

  1. 一个基于J2EE的web应用程序运行起来需要什么?

    2019独角兽企业重金招聘Python工程师标准>>> Eclipse ?IDEA?这是目前市面上最常用的开发工具啦,我的理解是这些只是开发工具,是为了方便开发的,而不是web应用程 ...

  2. 使用Docker构建并测试web应用程序

    使用Docker构建并测试web应用程序 构建Sinatra应用程序 构建Dockerfile FROM ubuntu:lastest MAINTAINER James Turnbull james@ ...

  3. java 插桩 工具_一个基于Eclipse的通用Java程序插桩工具.pdf

    第38卷第7期 计算机科学 V01.38NO.7 Science 2011 2011年7月 Computer July 一个基于Eclipse的通用Java程序插桩工具 郑晓梅 (南京中医药大学信息技 ...

  4. AVR单片机计算器C语言源程序,一个基于AVR单片机的计算器程序.doc

    一个基于AVR单片机的计算器程序 #include #include//延时函数的头文件 #include // 中断函数的头文件 #define uint unsigned int #define ...

  5. 一个非常轻巧的基于Groovy的Web应用程序项目模板

    一个非常轻巧的基于Groovy的Web应用程序项目模板 您可能听说过该项目Grails是Ruby on Rails之类的Groovy版本的框架,该框架使您可以通过动态脚本轻松地创建Web应用程序. 尽 ...

  6. groovy 模板_一个非常轻巧的基于Groovy的Web应用程序项目模板

    groovy 模板 一个非常轻巧的基于Groovy的Web应用程序项目模板 您可能听说过该项目Grails是Ruby on Rails之类的Groovy版本的框架,该框架使您可以通过动态脚本更轻松地创 ...

  7. 属于服务器端运行的程序_Telerik UI for ASP.NET MVC:为任何设备以两倍的速度构建功能丰富且响应迅速的web应用程序...

    Telerik UI for ASP.NET MVC 为任何设备以两倍的速度构建功能丰富且响应迅速的web应用程序.由Kendo UI提供支持 主要功能 适用于任何应用场景的UI框架 享受满足各种需求 ...

  8. spring_在基于Spring的Web应用程序中使用Http Session

    spring 在基于Spring的Web应用程序中拥有和使用Http会话有多种方法. 这是基于最近项目经验的总结. 方法1 只需在需要的HttpSession中注入即可. @Service publi ...

  9. 在Autodesk应用程序商店发布基于浏览器的Web应用程序

    你一定已经听说过Autodesk应用程序商店了,通过Autodesk应用程序商店,你可以免费下载或购买来自全球的优秀开发者发布的应用程序,来帮助你更快更方便的完成你的工作.而且作为开发者,您也可以在A ...

最新文章

  1. linux ubuntu安装 mono,在Ubuntu 18.04系统中安装Mono及基本使用Mono的方法
  2. 在Windows下,用Hexo搭建博客
  3. Ubuntu 16.04 LTS 下安装PyCharm
  4. SecureCRT SSH 语法高亮
  5. Parallels Desktop虚拟机无法关机提示“虚拟机处理器已被操作系统重置”
  6. PAT乙级(1020 月饼)
  7. 考研计算机网络,2020计算机专业考研的计算机网络部分知识点
  8. ONVIF流媒体播放流程
  9. 6688常见问题FAQ
  10. 计算机单位厘米 像素,英尺和厘米的换算计算器 显示器的像素解析度可能不是...
  11. VIN码/车架号的详解,车架号识别,VIN码识别,OCR车架号识别能带来什么
  12. CodeWarrior IDE烧写介绍
  13. 简单的网站全屏背景图代码
  14. oracle remap schema,impdp的remap_schema选项的另一个schema是否要重建
  15. 全球首位亿万富豪上太空!
  16. 这四十年来的香港歌坛在唱些什么,“南中国听歌最多”的数据分析师带你一探究竟...
  17. Java 接口的定义、接口的成语、接口的实现、接口与类的多继承、JDK1.8后新增方法、使用接口的注意事项
  18. 爱普生photo EX3打印机四个灯同时闪的解决方法
  19. RabbitMq消息队列进一步认识
  20. 反相畴的基础知识和一篇论文

热门文章

  1. Spring 中的编程思想总结
  2. 项目中applicaiton.yml配置文件详细讲解
  3. 搭建项目前端页面环境
  4. 注解IOC案例-把自己编写的类使用注解配置
  5. ES6新特性之扩展运算符
  6. hystrix-dashboard
  7. SpringBoot_web开发-SpringMVC自动配置原理
  8. android和web api接口,WebService和Webapi的区别
  9. mysql 界面 创建用户名和密码是什么_PLSQL操作Oracle创建用户和表(含创建用户名和密码)...
  10. Java:ThreadPoolExecutor解析续--Executors