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]].