aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Gerrand <adg@golang.org>2014-09-27 07:41:29 +1000
committerAndrew Gerrand <adg@golang.org>2014-09-27 07:41:29 +1000
commit4b745528cbfa9e2ef12d6093cb5babcd76c5bfca (patch)
tree37ac1e6d0423973da128eb51c397dd50538f53a4
parent63173935e06d26c8f9295a191577355d6f0d15b7 (diff)
go.blog: add Docker article
LGTM=r R=r CC=golang-codereviews https://golang.org/cl/148190043
-rw-r--r--content/docker-outyet.pngbin0 -> 59928 bytes
-rw-r--r--content/docker.article201
2 files changed, 201 insertions, 0 deletions
diff --git a/content/docker-outyet.png b/content/docker-outyet.png
new file mode 100644
index 0000000..c5e5710
--- /dev/null
+++ b/content/docker-outyet.png
Binary files differ
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]].