未加星标

Developing a Go app with Docker Compose

字体大小 | |
[数据库(综合) 所属分类 数据库(综合) | 发布者 店小二04 | 时间 2016 | 作者 红领巾 ] 0人收藏点击收藏

Writing Go applications in an isolated environment with Docker comes with some great advantages. You get a clean GOPATH, the bare essentials for developing, and you can easily change which Go version you’re developing against.

In this quick tutorial, we’re going to show you how to structure a Go application with Docker Compose as your development environment.

GettingStarted

First off, if you haven’t installed Docker or gone through some of the basics, you can checkout the free guide onblindside.io. It will take you through installation and basics.

Project Structure

When developing with Docker Compose + Go, it really doesn’t matter where you create your project in your machine. If your GOPATH is set to ~/development/go, you can still create your projects inside of ~/Desktop and it won’t really matter. However, please don’t create projects on your desktop.

With that said, I still recommend putting all of your apps in your GOPATH as it makes things consistent and if someone hops on your machine to assist in debugging things, everything should be where they normally are.

Let’s create a new project called “go-with-compose” in our GOPATH:

$ mkdir $GOPATH/src/go-with-compose

Inside of this folder we’re going to have a couple of files:

docker-compose.yml
main.go

To get started, we’ll just make a super simple main.go with hello world inside of it:

# main.go
package main
import "fmt"
func main() {
fmt.Println("Hello World")
}

In our docker-compose.yml file, we’re going to add a service that uses a Go image like so:

version: "2"
services:
app:
image: golang:1.6.1-alpine

I like using the Alpine variant of the Go image because it’s slim but still has everything I normally would use in a Go application.

At this point we can actually run a simple command using compose:

$ docker-compose run app go env
GOARCH="amd64"
GOBIN=""
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/go"
GORACE=""
GOROOT="/usr/local/go"
GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"
GO15VENDOREXPERIMENT="1"
CC="gcc"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0"
CXX="g++"
CGO_ENABLED="1"

This will print our environment for inside of our container. What we’re interested in from this output is the GOPATH for the Go Docker image. Which we see is /go/src

Now what we can do is mount our projects directory inside of the container by modifying our docker-compose.yml file.

version: "2"
services:
app:
image: golang:1.6.1-alpine
volumes:
- .:/go/src/go-with-compose

You can see here that we’re mounting the current directory to the directory /go/src/go-with-compose inside of the running app container.

Now, what we can do, is change the working directory to the path of our application when we run any command inside of this container:

version: "2"
services:
app:
image: golang:1.6.1-alpine
volumes:
- .:/go/src/go-with-compose
working_dir: /go/src/go-with-compose

This allows us to run Go commands easily for our project like so:

$ docker-compose run app go run main.go

Huzzah! We’ve run our main.go file inside of a container initialized by Docker Compose. But why stop there?

One of the main reasons for docker compose is to easily start your containers with docker-compose up. But if we run that now we’ll actually see an error as the Go image doesn’t define a CMD instruction, and our compose file omits a default command as well.

So what we can do is add a default command to run when starting our application with up:

version: "2"
services:
app:
image: golang:1.6.1-alpine
volumes:
- .:/go/src/go-with-compose
working_dir: /go/src/go-with-compose
command: go run main.go

Now we can run a simple:

$ docker-compose up

And voila! We see our simple hello world application running.

RunningTests

With all of the test you’ve been writing for your Go application (right?!), you’ll probably want to run them inside of this environment as well. This is easy to do. We can run the following command in our terminal:

$ docker-compose run app go test -v ./...

This should run all of the tests in the directory of your project. go test will be run from the correct directory because of the working_dir configuration we provided in our compose yaml.

Using aDatabase

A lot of the time we’re writing and reading data from a database. In a local setting we’d normally just run the database on our machine as a normal process. However, in Docker land, we won’t have access to that database. We’ll need to start a database in a separate container and connect to that. Luckily this is drop-dead simple with Docker Compose.

Let’s add a bit more to our docker-compose.yml file:

version: "2"
services:
app:
image: golang:1.6.1-alpine
volumes:
- .:/go/src/go-with-compose
working_dir: /go/src/go-with-compose
command: go run main.go
links:
- redis
redis:
image: redis:alpine

We’ve done 2 things here:

Added a links declaration to our app service definition. Added a new service called redis using the image redis alpine.

No we can modify our main.go file to connect to Redis and do a simple PING command and print the result:

package main
import (
"fmt"
redis "gopkg.in/redis.v4"
)
func main() {
client := redis.NewClient(&redis.Options{
Addr: "redis:6379",
Password: "", // no password set
DB: 0, // use default DB
})
pong, err := client.Ping().Result()
fmt.Println(pong, err)
}

Now lets try our our new docker-compose.yml file and Go program:

$ docker-compose up

You’ll see the Redis server start up and… an error? Crap.

app_1 | main.go:6:2: cannot find package "gopkg.in/redis.v4" in any of:
app_1 | /usr/local/go/src/gopkg.in/redis.v4 (from $GOROOT)
app_1 | /go/src/gopkg.in/redis.v4 (from $GOPATH)

Since our container has a separate file system than our host machine, we need to make sure the redis package is available in the container at runtime. This is easily solved using the vendoring capability introduced in Go 1.5 (with the vendor experiment feature enabled). Since our Go program is running inside of a 1.6.x Go container, we can simply add the redis package to the vendor directory since we’re mounting the entire directory into the container at runtime.

Vendoring Our Dependencies

To vendor our project's dependencies, I highly recommend the govendor tool (https://github.com/kardianos/govendor).

$ go get -u github.com/kardianos/govendor
# Make sure you're in the correct project directory
$ govendor init
$ govendor add +external

Now our project should have a vendor directory with our dependencies. We should be able to re-try our docker-compose up:

$ docker-compose up
...
app_1 | PONG <nil>
...

If we look closely into the output from our command, we should see the pong value returned from the redis server.

Being More12Factor

Now in our connection configuration, we’ve declared the address for the Redis server like so:

client := redis.NewClient(&redis.Options{
Add

本文数据库(综合)相关术语:系统安全软件

主题: DockerRedisCGRIMPON
分页:12
转载请注明
本文标题:Developing a Go app with Docker Compose
本站链接:http://www.codesec.net/view/480258.html
分享请点击:


1.凡CodeSecTeam转载的文章,均出自其它媒体或其他官网介绍,目的在于传递更多的信息,并不代表本站赞同其观点和其真实性负责;
2.转载的文章仅代表原创作者观点,与本站无关。其原创性以及文中陈述文字和内容未经本站证实,本站对该文以及其中全部或者部分内容、文字的真实性、完整性、及时性,不作出任何保证或承若;
3.如本站转载稿涉及版权等问题,请作者及时联系本站,我们会及时处理。
登录后可拥有收藏文章、关注作者等权限...
技术大类 技术大类 | 数据库(综合) | 评论(0) | 阅读(40)