这是一次使用docker-compose搭建的可以横向扩展的web application“架构”。说架构有点大,但整体的思路的确可以作为框架选型有参考价值。
我在这次实践中所使用的技术栈有:
1. sinatra: 一个非常简单的ruby的web框架
2. docker
3. docker-compose
直接进入正文
为什么要构建一个简单的base image? 这方便我们在构建项目的时候,统一一下环境。本次实践构建的base image非常简单。代码如下
FROM ruby:2.3.0
gem install sinatra
构建命令: docker build -t xudonghe/sinatra:v1 .
构建完成后,我们可以运行 docker images
查看结果
第一步,新建一个简单的app.rb 文件
第二部,输入如下代码
require 'sinatra'
set :bind, '0.0.0.0'
get '/' do
'Hello world!'
end
这里有一个值得注意的地方是,需要设置将服务器绑定在 0.0.0.0
地址上,否则 容器外部将无法访问。
该文件主要在于用来启动web application
#!/bin/bash
ruby -rubygems app.rb
FROM xudonghe/sinatra:v2
EXPOSE 4567
COPY . /app
WORKDIR /app
RUN chmod a+x ./start.sh
CMD ["bash", "start.sh"]
为啥继承的是xudonghe/sinatra:v2
?因为我在本地构建了一个新的版本,其实很简单。就是开了 4567
端口,并且将文件复制到了容器中。在新的构建文件中,我给start.sh
赋予了可执行权限,并在容器启动的时候,会运行该文件。
运行如下测试命令
docker build -t xudonghe/sinatra:v3 .
docker run --rm -ti -P -v $(pwd):/app xudonghe/sinatra:v3 ruby -rubygems app.rb
然后在本地访问
curl http://$(docker-machine ip):4567
整个系统中,就有两个组件:web 和 nginx-proxy. 我选用的是 jwilder/nginx-proxy. 使用比较简单。 先将镜像下载到本地 : docker pull jwilder/nginx-proxy
. 然后运行 docker run -d -p 80:80 -v /var/run/docker.sock:/tmp/docker.sock:ro jwilder/nginx-proxy
. 当然,如果需要使用 docker-compose , 我们就不需要这么手动启动。 这里只是做一个简单的介绍。如果需要继续下去,需要关闭这个容器。
如下是我的docker-compose.yml
文件
web:
build: .
volumes:
- .:/app
expose:
- 4567
environment:
- VIRTUAL_HOST=yourwebsiteurl
nginx:
image: jwilder/nginx-proxy:latest
links:
- web
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
ports:
- 80:80
- 443:443
此处有一个关键的地方
1. 环境变量要定义好 environment
environment:
- VIRTUAL_HOST=yourwebsiteurl
/var/run/docker.sock:/tmp/docker.sock:ro
docker-compose up -d
docker-compose scale web=5
docker-compose ps
http://yourwebsite
如果要按照上面的代码实践的话,一般不会成功。因为还缺少一些必要的条件:本地的nginx 做反向代理 和修改 本地 /etc/hosts 文件,将web地址指向docker. 这里就不在详细说明了。 具体的架构图如下:
其中 nginx
是在 host 机上, nginx-proxy
在 docker 中
该方案的优点在于非常容易对项目进行横向扩充,缺点在于优点复杂。