github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/blog/content/docker.article (about) 1 Deploying Go servers with Docker 2 26 Sep 2014 3 4 Andrew Gerrand 5 6 * Introduction 7 8 This week Docker [[https://blog.docker.com/2014/09/docker-hub-official-repos-announcing-language-stacks/][announced]] 9 official base images for Go and other major languages, 10 giving programmers a trusted and easy way to build containers for their Go programs. 11 12 In this article we'll walk through a recipe for creating a Docker container for 13 a simple Go web application and deploying that container to Google Compute Engine. 14 If you're not familiar with Docker, you should read 15 [[http://docs.docker.com/introduction/understanding-docker/][Understanding Docker]] 16 before reading on. 17 18 * The demo app 19 20 For our demonstration we will use the 21 [[http://godoc.org/github.com/golang/example/outyet][outyet]] program from the 22 [[https://github.com/golang/example][Go examples repository]], 23 a simple web server that reports whether the next version of Go has been released 24 (designed to power sites like [[http://isgo1point4.outyet.org/][isgo1point4.outyet.org]]). 25 It has no dependencies outside the standard library and requires no additional 26 data files at run time; for a web server, it's about as simple as it gets. 27 28 Use "go get" to fetch and install outyet in your 29 [[http://golang.org/doc/code.html#Workspaces][workspace]]: 30 31 $ go get github.com/golang/example/outyet 32 33 * Write a Dockerfile 34 35 Replace a file named `Dockerfile` in the `outyet` directory with the following contents: 36 37 # Start from a Debian image with the latest version of Go installed 38 # and a workspace (GOPATH) configured at /go. 39 FROM golang 40 41 # Copy the local package files to the container's workspace. 42 ADD . /go/src/github.com/golang/example/outyet 43 44 # Build the outyet command inside the container. 45 # (You may fetch or manage dependencies here, 46 # either manually or with a tool like "godep".) 47 RUN go install github.com/golang/example/outyet 48 49 # Run the outyet command by default when the container starts. 50 ENTRYPOINT /go/bin/outyet 51 52 # Document that the service listens on port 8080. 53 EXPOSE 8080 54 55 This `Dockerfile` specifies how to construct a container that runs `outyet`, 56 starting with the basic dependencies (a Debian system with Go installed; 57 the [[https://registry.hub.docker.com/_/golang/][official `golang` docker image]]), 58 adding the `outyet` package source, building it, and then finally running it. 59 60 The `ADD`, `RUN`, and `ENTRYPOINT` steps are common tasks for any Go project. 61 To simplify this, there is an 62 [[https://github.com/docker-library/golang/blob/9ff2ccca569f9525b023080540f1bb55f6b59d7f/1.3.1/onbuild/Dockerfile][`onbuild` variant]] 63 of the `golang` image that automatically copies the package source, fetches the 64 application dependencies, builds the program, and configures it to run on 65 startup. 66 67 With the `onbuild` variant, the `Dockerfile` is much simpler: 68 69 FROM golang:onbuild 70 EXPOSE 8080 71 72 * Build and run the image 73 74 Invoke Docker from the `outyet` package directory to build an image using the `Dockerfile`: 75 76 $ docker build -t outyet . 77 78 This will fetch the `golang` base image from Docker Hub, copy the package source 79 to it, build the package inside it, and tag the resulting image as `outyet`. 80 81 To run a container from the resulting image: 82 83 $ docker run --publish 6060:8080 --name test --rm outyet 84 85 The `--publish` flag tells docker to publish the container's port `8080` on the 86 external port `6060`. 87 88 The `--name` flag gives our container a predictable name to make it easier to work with. 89 90 The `--rm` flag tells docker to remove the container image when the outyet server exits. 91 92 With the container running, open `http://localhost:6060/` in a web browser and 93 you should see something like this: 94 95 .image docker-outyet.png 96 97 (If your docker daemon is running on another machine (or in a virtual machine), 98 you should replace `localhost` with the address of that machine. If you're 99 using [[http://boot2docker.io/][boot2docker]] on OS X or Windows you can find 100 that address with `boot2docker`ip`.) 101 102 Now that we've verified that the image works, shut down the running container 103 from another terminal window: 104 105 $ docker stop test 106 107 * Create a repository on Docker Hub 108 109 [[https://hub.docker.com/][Docker Hub]], the container registry from which we 110 pulled the `golang` image earlier, offers a feature called 111 [[http://docs.docker.com/docker-hub/builds/][Automated Builds]] that builds 112 images from a GitHub or BitBucket repository. 113 114 By committing [[https://github.com/golang/example/blob/master/outyet/Dockerfile][the Dockerfile]] 115 to the repository and creating an 116 [[https://registry.hub.docker.com/u/adg1/outyet/][automated build]] 117 for it, anyone with Docker installed can download and run our image with a 118 single command. (We will see the utility of this in the next section.) 119 120 To set up an Automated Build, commit the Dockerfile to your repo on 121 [[https://github.com/][GitHub]] or [[https://bitbucket.org/][BitBucket]], 122 create an account on Docker Hub, and follow the instructions for 123 [[http://docs.docker.com/docker-hub/builds/][creating an Automated Build]]. 124 125 When you're done, you can run your container using the name of the automated build: 126 127 $ docker run goexample/outyet 128 129 (Replace `goexample/outyet` with the name of the automated build you created.) 130 131 * Deploy the container to Google Compute Engine 132 133 Google provides 134 [[https://developers.google.com/compute/docs/containers/container_vms][container-optimized Google Compute Engine images]] 135 that make it easy to spin up a virtual machine running an arbitrary Docker container. 136 On startup, a program running on the instance reads a configuration file that 137 specifies which container to run, fetches the container image, and runs it. 138 139 Create a [[https://cloud.google.com/compute/docs/containers/container_vms#container_manifest][containers.yaml]] 140 file that specifies the docker image to run and the ports to expose: 141 142 version: v1beta2 143 containers: 144 - name: outyet 145 image: goexample/outyet 146 ports: 147 - name: http 148 hostPort: 80 149 containerPort: 8080 150 151 (Note that we're publishing the container's port `8080` as external port `80`, 152 the default port for serving HTTP traffic. And, again, you should replace 153 `goexample/outyet` with the name of your Automated Build.) 154 155 Use the [[https://cloud.google.com/sdk/#Quick_Start][gcloud tool]] 156 to create a VM instance running the container: 157 158 $ gcloud compute instances create outyet \ 159 --image container-vm-v20140925 \ 160 --image-project google-containers \ 161 --metadata-from-file google-container-manifest=containers.yaml \ 162 --tags http-server \ 163 --zone us-central1-a \ 164 --machine-type f1-micro 165 166 The first argument (`outyet`) specifies the instance name, a convenient label 167 for administrative purposes. 168 169 The `--image` and `--image-project` flags specify the special 170 container-optimized system image to use (copy these flags verbatim). 171 172 The `--metadata-from-file` flag supplies your `containers.yaml` file to the VM. 173 174 The `--tags` flag tags your VM instance as an HTTP server, adjusting the 175 firewall to expose port 80 on the public network interface. 176 177 The `--zone` and `--machine-type` flags specify the zone in which to run the VM 178 and the type of machine to run. (To see a list of machine types and the zones, 179 run `gcloud`compute`machine-types`list`.) 180 181 Once this has completed, the gcloud command should print some information about 182 the instance. In the output, locate the `networkInterfaces` section to find the 183 instance's external IP address. Within a couple of minutes you should be able 184 to access that IP with your web browser and see the "Has Go 1.4 been released 185 yet?" page. 186 187 (To see what's happening on the new VM instance you can ssh into it with 188 `gcloud`compute`ssh`outyet`. From there, try `sudo`docker`ps` to see which 189 Docker containers are running.) 190 191 * Learn more 192 193 This is just the tip of the iceberg—there's a lot more you can do with Go, Docker, and Google Compute Engine. 194 195 To learn more about Docker, see their [[https://docs.docker.com/][extensive documentation]]. 196 197 To learn more about Docker and Go, see the [[https://registry.hub.docker.com/_/golang/][official `golang` Docker Hub repository]] and Kelsey Hightower's [[https://medium.com/@kelseyhightower/optimizing-docker-images-for-static-binaries-b5696e26eb07][Optimizing Docker Images for Static Go Binaries]]. 198 199 To learn more about Docker and [[http://cloud.google.com/compute][Google Compute Engine]], 200 see the [[https://cloud.google.com/compute/docs/containers/container_vms][Container-optimized VMs page]] 201 and the [[https://registry.hub.docker.com/u/google/docker-registry/][google/docker-registry Docker Hub repository]].