用Docker定制Golang+Gin+Mongodb+Nginx的开发环境
本文是我日常搭建Docker开发环境的很常用的方式,通过docker搭建一个web的开发环境,能让我们直观了解Docker的工作方式。 本文的例子,为了方便演示,我都是搭建在同一台主机上的,但日常生产环境中比较多的情况是跨主机跨容器交互,我们需要 用到代理镜像的手段解决跨宿主机的通讯, 具体可以参考 官方的 ambassador 配置方式。
在搭建之前,我们先设置一些目录存放我们的Dockerfile, 约定参考如下:
$ mkdir -p /data/apps/mytest/mongodb/
$ mkdir -p /data/apps/mytest/go/
$ mkdir -p /data/apps/mytest/nginx/
我们搭建的服务器ip假设为
192.168.139.140
,下文都以这个地址作为我们服务器地址下面的镜像默认以ubuntu作为根镜像
构建MongoDB镜像
MongoDB是一款流行的开放源码的非关系型数据库系统(NoSQL),常用于大数据量、高并 发、弱事务的互联网应用。MongoDB的官网地址是http://www.mongodb.com/ 将MongoDB数据 库系统容器化可以带来以下几个好处。
更容易维护。
启动速度快。
方便与他人进行分享。
编写Dockerfile
进入 /data/apps/mytest/mongodb/
创建我们的Dockerfile文件,内容如下:
FROM ubuntu:14.04
MAINTAINER lihaoquan quanix@163.com
RUN apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 7F0CEB10
RUN echo "deb http://repo.mongodb.org/apt/ubuntu "$(lsb_release -sc)"/mongodb-org/3.0 multiverse" | tee /etc/apt/sources.list.d/mongodb-org-3.0.list
RUN apt-get update && apt-get install -y --force-yes mongodb-org
RUN apt-get update && apt-get install -y --force-yes mongodb-org=3.0.1 mongodb-org-server=3.0.1 mongodb-org-shell=3.0.1 mongodb-org-mongos=3.0.1 mongodb-org-tools=3.0.1
RUN mkdir -p /data/db
EXPOSE 27017
ENTRYPOINT ["/usr/bin/mongod"]
构建镜像
有了Dockerfile之后,进入Dockerfile文件所在的目录,然后使用build命令来构建镜像:
具体命令参考如下:
sudo docker build --tag lihaoquan/mongodb3 .
构建容器
镜像都建立成功后,我们可以基于镜像构建我们的容器:
sudo docker run -p 27017:27017 --name mongodb_instance -d lihaoquan/mongodb3
这时,我们可以运行 sudo docker ps -a 看我们的容器是否运行起来了。
我们就测试下mongodb的服务是否ok:
我们找一个安装有mongo客户端,然后尝试连接下我们的服务
mongo -port 21017 --host:192.168.139.140
如果顺利连接上,证明我们我们mongodb容器服务已经正常对外提供服务了。
接下来我们可以动手编写一个简单的go服务端并连接我们的mongodb服务,为用户提供查询服务。
构建golang镜像
Gin是基于Go的web开发框架,它具有类似Martini风格的API接口,如果你需要一个高性能的访问速度, 选择它无非是最好的选择。看过Beego、Martini的代码,感觉还是gin符合我的口味。
Gin相关资料:
在构建go容器之前,我们先写一个简单的运行例子:
我们进入 /data/apps/mytest/go/
然后创建一个 main.go 的文件,前后敲入以下的内容:
package main
import (
"fmt"
"github.com/gin-gonic/gin"
"gopkg.in/mgo.v2"
"gopkg.in/mgo.v2/bson"
"net/http"
)
type Book struct {
Name string
Sn string
}
//测试查询
func TestFindBook(c *gin.Context) {
sn, _ := c.GetQuery("sn")
if sn == "" {
sn = "1"
}
session, err := mgo.Dial("mongo_server")
if err != nil {
panic(err)
} else {
println("连接成功")
}
collections := session.DB("test").C("book")
book := Book{}
err = collections.Find(bson.M{"sn": sn}).One(&book)
if err != nil {
}
c.String(http.StatusOK, fmt.Sprintf("find book : %s", book.Name))
}
func TestInsertBook(c *gin.Context) {
sn, _ := c.GetQuery("sn")
name, _ := c.GetQuery("name")
res := "no insert"
if sn != "" && name != "" {
session, err := mgo.Dial("mongo_server")
if err != nil {
panic(err)
} else {
println("连接成功")
}
collections := session.DB("test").C("book")
book := &Book{
Name: name,
Sn: sn,
}
err = collections.Insert(book)
if err != nil {
res = "no insert"
}
res = "insert!"
}
c.String(http.StatusOK, res)
}
func RegisterRoutes(r *gin.Engine) {
r.GET("/", func(c *gin.Context) {
c.String(http.StatusOK, "hello docker !")
})
r.GET("/book", func(c *gin.Context) {
TestFindBook(c)
})
r.GET("/insert", func(c *gin.Context) {
TestInsertBook(c)
})
}
func main() {
r := gin.New()
RegisterRoutes(r)
r.Run(":8000")
select {}
}
编写Dockerfile
go服务端程序编写后,在同级目录下创建Dockerfile文件,然后输入以下内容
FROM golang:onbuild
EXPOSE 8000
可以发现,这个Dockerfile非常简单,golang:onbuild为我们提供基础镜像,并进行相关命令封装。
golang:onbuild
会为我们省略了很多的设置步骤,包括ADD、WORKDIR、CMD等设置命令,我们只需要按照规范在项目目录下放置main.go即可。
构建镜像
接着,我们开始创建一个go web应用镜像
sudo docker build -t goapp .
构建容器
最后,基于这个镜像,我们构建我们的容器,并暴露指定的端口和链接到我们的mongodb容器上:
sudo docker run -d --name goapp_api -p 8000:8000 --link mongodb_instance:mongo_server goapp
我们在浏览器上访问 : http://192.168.139.140:8000
OK, web服务已经搭建起来了。我们现在可以插入一些数据来测试我们web服务的存储功能:
我们在浏览器输入 : http://192.168.139.140:8000/insert?name=golang in action&sn=2
如果页面输出 insert!
则,表示已经成功插入一条数据。
我们再通过浏览器访问: http://192.168.139.140:8000/book?sn=2
若如下图所示, 则我们已经成功通过docker部署了一个gin+mongodb的容器服务。
有了基本的web应用服务后,我们要着手为它配置负载,反向代理等功能,毕竟这是互联网生产环境的标配,所以下面我们
增加nginx的支持,继续扩展一下我们的架构
吧。
构建Nginx 镜像
Nginx是一款支持HTTP、HTTPS、SMTP、POP3、IMAP等协议的反向代理服务器,也常用 作负载均衡、HTTP缓存和Web服务器。由于它开源、配置简单以及拥有高并发、高性能、低内 存、稳定性高等诸多优良特性,目前已经成为互联网上应用最广泛的Web服务器之一。 本案例以Nginx作为前端服务器,主要提供两方面的功能:
提供静态页面的访问服务;
goapp_api反向代理服务。
创建自定义配置文件
进入 /data/apps/mytest/nginx/
创建nginx.conf
,内容如下:
worker_processes 4;
events { worker_connections 1024; }
http {
upstream go-app {
server 192.168.139.140:8000;
}
server {
listen 80;
location / {
proxy_pass http://go-app;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
}
我们准备使用这个配置文件来取代nginx的默认配置文件,这需要我们的Dockerfile进行相关配置。
编写Dockerfile
同级目录下,创建Dockerfile
FROM nginx
MAINTAINER lihaoquan quanix@163.com
COPY nginx.conf /etc/nginx/nginx.conf
上面的Dockerfile,我们把自定义的nginx.conf
拷贝到/etc/nginx/nginx.conf
这样ngix就会把我们的配置文件作为默认配置文件。
构建镜像
sudo docker build -t lihaoquan/nginx .
构建容器
sudo docker run -d --name nginx_web -p 80:80 lihaoquan/nginx
上面的例子,我们在nginx.conf设置了具体的ip地址
192.168.139.140
, 如果希望使用别名,而不是具体IP配置, 可以先设置别名goapp_api ,然后构建命令需要进行容器连接 :$ sudo docker run -d --name nginx_web -p 80:80 --link goapp_api:goapp_api lihaoquan/nginx
我们将容器内的80端口
直接映射到外网
验证web应用
我们在浏览器输入:http://192.168.139.140/book?sn=2
来看我们的查询服务是否已经通过nginx代理:
如果能展示下图的输出:
证明,我们的nginx的代理服务已经生效了。
总结
使用同样的方法,我们也可以配置 docker + nodejs + mongodb + nginx的配置,具体的方法,大家可以动手试试。