diff options
author | Andrew Gerrand <adg@golang.org> | 2014-09-27 07:41:29 +1000 |
---|---|---|
committer | Andrew Gerrand <adg@golang.org> | 2014-09-27 07:41:29 +1000 |
commit | 4b745528cbfa9e2ef12d6093cb5babcd76c5bfca (patch) | |
tree | 37ac1e6d0423973da128eb51c397dd50538f53a4 | |
parent | 63173935e06d26c8f9295a191577355d6f0d15b7 (diff) |
go.blog: add Docker article
LGTM=r
R=r
CC=golang-codereviews
https://golang.org/cl/148190043
-rw-r--r-- | content/docker-outyet.png | bin | 0 -> 59928 bytes | |||
-rw-r--r-- | content/docker.article | 201 |
2 files changed, 201 insertions, 0 deletions
diff --git a/content/docker-outyet.png b/content/docker-outyet.png Binary files differnew file mode 100644 index 0000000..c5e5710 --- /dev/null +++ b/content/docker-outyet.png diff --git a/content/docker.article b/content/docker.article new file mode 100644 index 0000000..90c8e66 --- /dev/null +++ b/content/docker.article @@ -0,0 +1,201 @@ +Deploying Go servers with Docker +26 Sep 2014 + +Andrew Gerrand + +* Introduction + +This week Docker [[https://blog.docker.com/2014/09/docker-hub-official-repos-announcing-language-stacks/][announced]] +official base images for Go and other major languages, +giving programmers a trusted and easy way to build containers for their Go programs. + +In this article we'll walk through a recipe for creating a Docker container for +a simple Go web application and deploying that container to Google Compute Engine. +If you're not familiar with Docker, you should read +[[http://docs.docker.com/introduction/understanding-docker/][Understanding Docker]] +before reading on. + +* The demo app + +For our demonstration we will use the +[[http://godoc.org/github.com/golang/example/outyet][outyet]] program from the +[[https://github.com/golang/example][Go examples repository]], +a simple web server that reports whether the next version of Go has been released +(designed to power sites like [[http://isgo1point4.outyet.org/][isgo1point4.outyet.org]]). +It has no dependencies outside the standard library and requires no additional +data files at run time; for a web server, it's about as simple as it gets. + +Use "go get" to fetch and install outyet in your +[[http://golang.org/doc/code.html#Workspaces][workspace]]: + + $ go get github.com/golang/example/outyet + +* Write a Dockerfile + +Create a file named `Dockerfile` in the `outyet` directory with the following contents: + + # Start from a Debian image with the latest version of Go installed + # and a workspace (GOPATH) configured at /go. + FROM golang + + # Copy the local package files to the container's workspace. + ADD . /go/src/github.com/golang/example/outyet + + # Build the outyet command inside the container. + # (You may fetch or manage dependencies here, + # either manually or with a tool like "godep".) + RUN go install github.com/golang/example/outyet + + # Run the outyet command by default when the container starts. + ENTRYPOINT /go/bin/outyet + + # Document that the service listens on port 8080. + EXPOSE 8080 + +This `Dockerfile` specifies how to construct a container that runs `outyet`, +starting with the basic dependencies (a Debian system with Go installed; +the [[https://registry.hub.docker.com/_/golang/][official `golang` docker image]]), +adding the `outyet` package source, building it, and then finally running it. + +The `ADD`, `RUN`, and `ENTRYPOINT` steps are common tasks for any Go project. +To simplify this, there is an +[[https://github.com/docker-library/golang/blob/9ff2ccca569f9525b023080540f1bb55f6b59d7f/1.3.1/onbuild/Dockerfile][`onbuild` variant]] +of the `golang` image that automatically copies the package source, fetches the +application dependencies, builds the program, and configures it to run on +startup. + +With the `onbuild` variant, the `Dockerfile` is much simpler: + + FROM golang:onbuild + EXPOSE 8080 + +* Build and run the image + +Invoke Docker from the package directory to build an image using the `Dockerfile`: + + $ docker build -t outyet . + +This will fetch the `golang` base image from Docker Hub, copy the package source +to it, build the package inside it, and tag the resulting image as `outyet`. + +To run a container from the resulting image: + + $ docker run --publish 6060:8080 --name test --rm outyet + +The `--publish` flag tells docker to publish the container's port `8080` on the +external port `6060`. + +The `--name` flag gives our container a predictable name to make it easier to work with. + +The `--rm` flag tells docker to remove the container image when the outyet server exits. + +With the container running, open `http://localhost:6060/` in a web browser and +you should see something like this: + +.image docker-outyet.png + +(If your docker daemon is running on another machine (or in a virtual machine), +you should replace `localhost` with the address of that machine. If you're +using [[http://boot2docker.io/][boot2docker]] on OS X or Windows you can find +that address with `boot2docker`ip`.) + +Now that we've verified that the image works, shut down the running container +from another terminal window: + + $ docker stop test + +* Create a repository on Docker Hub + +[[https://hub.docker.com/][Docker Hub]], the container registry from which we +pulled the `golang` image earlier, offers a feature called +[[http://docs.docker.com/docker-hub/builds/][Automated Builds]] that builds +images from a GitHub or BitBucket repository. + +By committing [[https://github.com/golang/example/blob/master/outyet/Dockerfile][the Dockerfile]] +to the repository and creating an +[[https://registry.hub.docker.com/u/adg1/outyet/][automated build]] +for it, anyone with Docker installed can download and run our image with a +single command. (We will see the utility of this in the next section.) + +To set up an Automated Build, commit the Dockerfile to your repo on +[[https://github.com/][GitHub]] or [[https://bitbucket.org/][BitBucket]], +create an account on Docker Hub, and follow the instructions for +[[http://docs.docker.com/docker-hub/builds/][creating an Automated Build]]. + +When you're done, you can run your container using the name of the automated build: + + $ docker run goexample/outyet + +(Replace `goexample/outyet` with the name of the automated build you created.) + +* Deploy the container to Google Compute Engine + +Google provides +[[https://developers.google.com/compute/docs/containers/container_vms][container-optimized Google Compute Engine images]] +that make it easy to spin up a virtual machine running an arbitrary Docker container. +On startup, a program running on the instance reads a configuration file that +specifies which container to run, fetches the container image, and runs it. + +Create a [[https://cloud.google.com/compute/docs/containers/container_vms#container_manifest][containers.yaml]] +file that specifies the docker image to run and the ports to expose: + + version: v1beta2 + containers: + - name: outyet + image: goexample/outyet + ports: + - name: http + hostPort: 80 + containerPort: 8080 + +(Note that we're publishing the container's port `8080` as external port `80`, +the default port for serving HTTP traffic. And, again, you should replace +`goexample/outyet` with the name of your Automated Build.) + +Use the [[https://cloud.google.com/sdk/#Quick_Start][gcloud tool]] +to create a VM instance running the container: + + $ gcloud compute instances create outyet \ + --image container-vm-v20140826 \ + --image-project google-containers \ + --metadata-from-file google-container-manifest=containers.yaml \ + --tags http-server \ + --zone us-central1-a \ + --machine-type f1-micro + +The first argument (`outyet`) specifies the instance name, a convenient label +for administrative purposes. + +The `--image` and `--image-project` flags specify the special +container-optimized system image to use (copy these flags verbatim). + +The `--metadata-from-file` flag supplies your `containers.yaml` file to the VM. + +The `--tags` flag tags your VM instance as an HTTP server, adjusting the +firewall to expose port 80 on the public network interface. + +The `--zone` and `--machine-type` flags specify the zone in which to run the VM +and the type of machine to run. (To see a list of machine types and the zones, +run `gcloud`compute`machine-types`list`.) + +Once this has completed, the gcloud command should print some information about +the instance. In the output, locate the `networkInterfaces` section to find the +instance's external IP address. Within a couple of minutes you should be able +to access that IP with your web browser and see the "Has Go 1.4 been released +yet?" page. + +(To see what's happening on the new VM instance you can ssh into it with +`gcloud`compute`ssh`outyet`. From there, try `sudo`docker`ps` to see which +Docker containers are running.) + +* Learn more + +This is just the tip of the iceberg—there's a lot more you can do with Go, Docker, and Google Compute Engine. + +To learn more about Docker, see their [[https://docs.docker.com/][extensive documentation]]. + +To learn more about Docker and Go, see the [[https://registry.hub.docker.com/_/golang/][official golang Docker Hub repository]]. + +To learn more about Docker and [[http://cloud.google.com/compute][Google Compute Engine]], +see the [[https://cloud.google.com/compute/docs/containers/container_vms][Container-optimized VMs page]] +and the [[https://registry.hub.docker.com/u/google/docker-registry/][google/docker-registry Docker Hub repository]]. |