Gin Practice Serialization 9 Deploys Golang Application to Docker

  docker, golang, mysql, php

Deploying Golang Applications to Docker

Project address: …(Get on the bus and support the wave)
Original address: …


  • You need to install it before you start.docker, with a good mirror source
  • This chapter source code inf-20180324-dockerOn the branch
  • Starting from this chapter, the project catalog is based ongo-gin-exampleAs a benchmark (please be flexible with your local projects)


Here is a brief introduction to Docker, suggesting further study


Docker is an open source lightweight container technology that allows developers to package their applications and the context in which they run into a portable image and then publish it to any system that supports Docker. With container technology, Docker provides an isolated operating environment for applications with little performance overhead.

  • Simplify configuration
  • Code pipeline management
  • Improve development efficiency
  • Isolation application
  • Rapid and Continuous Deployment

Then we officially started the projectdockerFor the required processing and writing, each headline is a step outline.


I. writing Dockerfile

Ingo-gin-exampleThe project root directory creates a Dockerfile file and writes the contents

FROM golang:latest

RUN go build .

ENTRYPOINT ["./go-gin-example"]


golang:latestMirror is the basic mirror, and the working directory is set to$GOPATH/src/go-gin-exampleAnd copy the contents of the current context directory to the$GOPATH/src/go-gin-exampleIn

in handgo buildAfter compiling, set the container launcher to./go-gin-example, which is the executable we compiled

pay attention togo-gin-exampleIndockerCompiled in the container, not in the host site


Dockerfile file is a configuration file used to define the Docker image generation process. The file content is one instruction after another, and each instruction constructs a layer. Therefore, the content of each instruction describes how the layer should be constructed. These instructions apply to the base image and eventually create a new image.

You can think of it as a quick way to create a custom Docker image.


Specifies the base mirror (required instruction, and must be the first instruction)


The format isWORKDIR< working directory path >

UseWORKDIRInstructions can comeSpecify working directory(or called the current directory), the current directory of each layer will be changed to the specified directory. If the directory does not exist,WORKDIRWill help you create a directory



COPY <源路径>... <目标路径>
COPY ["<源路径1>",... "<目标路径>"]

COPYThe instruction will be from the file/directory < source path > in the build context directoryCopy< target path > location within the mirror to the new layer


Used to execute command line commands

Format:RUN< command >


The format isEXPOSE< port 1> [< port 2>…]

EXPOSEThe instruction isDeclare that the runtime container provides service ports, this is just a declarationThe application will not open the service of this port because of this declaration at runtime.

Writing such a declaration in Dockerfile has two benefits

  • Help mirror users understand the daemon port of this mirror service to facilitate mapping
  • When random port mapping is used at runtime, that isdocker run -PWhen, will automatically random mappingEXPOSEPort of


ENTRYPOINTThe format andRUNInstruction formats are the same, divided into two formats

  • execFormat:
  • shellFormat:
ENTRYPOINT [ "curl", "-s", "" ]

ENTRYPOINTThe instruction isSpecify container startup procedures and parameters

Second, build a mirror image

go-gin-exampleUnder the project root directory ofcarry out docker build -t gin-blog-docker .

The function of this command is to create/build a mirror image,-tThe specified name isgin-blog-docker,.The build content is the current context directory

$ docker build -t gin-blog-docker .
Sending build context to Docker daemon 96.39 MB
Step 1/6 : FROM golang:latest
 ---> d632bbfe5767
Step 2/6 : WORKDIR $GOPATH/src/
 ---> 56294f978c5d
Removing intermediate container e112997b995d
Step 3/6 : COPY . $GOPATH/src/
 ---> 3b60960120cf
Removing intermediate container 63e310b3f60c
Step 4/6 : RUN go build .
 ---> Running in 52648a431450

 ---> 7bfbeb301fea
Removing intermediate container 52648a431450
Step 5/6 : EXPOSE 8000
 ---> Running in 98f5b387d1bb
 ---> b65bd4076c65
Removing intermediate container 98f5b387d1bb
Step 6/6 : ENTRYPOINT ./go-gin-example
 ---> Running in c4f6cdeb667b
 ---> d8a109c7697c
Removing intermediate container c4f6cdeb667b
Successfully built d8a109c7697c

Third, verify the mirror image

Look at all the mirrors and make sure you just built themgin-blog-dockerDoes the mirror exist

$ docker images
REPOSITORY              TAG                 IMAGE ID            CREATED              SIZE
gin-blog-docker         latest              d8a109c7697c        About a minute ago   946 MB        latest              d632bbfe5767        8 days ago           779 MB

Four, create and run a new container

executive commanddocker run -p 8000:8000 gin-blog-docker

$ docker run -p 8000:8000 gin-blog-docker
dial tcp connect: connection refused
[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
 - using env:    export GIN_MODE=release
 - using code:    gin.SetMode(gin.ReleaseMode)

Actual pid is 1

The operation was successful. Do you think it is done?

You think too much, take a closer look at the console output for a mistake.dial tcp connect: connection refused

We studied and found thatMysqlWe will solve this problem in the second item.


First, pull the mirror image

FromDockerPublic warehouse ofDockerhubdownloadMySQLMirroring (a mirror image is recommended in China)

$ docker pull mysql

Second, create and run a new container

runMysqlContainer, and set the return container ID after successful execution

$ docker run --name mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=rootroot -d mysql

Connect Mysql

InitializedMysqlShould be as shown


Golang + Mysql

First, delete the mirror image

Because of the problem with the original mirror image, we need to delete it. There are several ways to do this.

  • Delete the original problematic mirror and rebuild a new one.
  • Rebuilding a DifferentnametagNew Mirror of

Delete the original problematic mirror image,-fIs forced deletion and its associated status

If not implemented-f, you need to performdocker ps -aThe associated container is found andrmRelieve the dependency between the two

$ docker rmi -f gin-blog-docker
Untagged: gin-blog-docker:latest
Deleted: sha256:d8a109c7697c3c2d9b4de7dbb49669d10106902122817b6467a031706bc52ab4
Deleted: sha256:b65bd4076c65a3c24029ca4def3b3f37001ff7c9eca09e2590c4d29e1e23dce5
Deleted: sha256:7bfbeb301fea9d8912a4b7c43e4bb8b69bdc57f0b416b372bfb6510e476a7dee
Deleted: sha256:3b60960120cf619181c1762cdc1b8ce318b8c815e056659809252dd321bcb642
Deleted: sha256:56294f978c5dfcfa4afa8ad033fd76b755b7ecb5237c6829550741a4d2ce10bc

Second, modify the configuration file

The project’s configuration fileconf/app.ini, the content is modified to

#debug or release
RUN_MODE = debug


HTTP_PORT = 8000

TYPE = mysql
USER = root
PASSWORD = rootroot
HOST = mysql:3306
NAME = blog

Third, rebuild the mirror image

Repeat the previous steps to return togin-blogUnder the project root directory ofcarry out docker build -t gin-blog-docker .

Four, create and run a new container


Q: We need to transferGolangContainers andMysqlContainers are linked, so what do we need to do?

A: add order--link mysql:mysqlLetGolangContainers andMysqlContainer interconnection; via--link,Can be accessed directly within the container using its associated container aliasAnd not through IP, but--linkOnly the association between single-machine containers can be solved, and in the case of distributed multi-machines, connections need to be made by other means.


executive commanddocker run --link mysql:mysql -p 8000:8000 gin-blog-docker

$ docker run --link mysql:mysql -p 8000:8000 gin-blog-docker
[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
 - using env:    export GIN_MODE=release
 - using code:    gin.SetMode(gin.ReleaseMode)
Actual pid is 1


Check that startup output, interface test and data in the database are normal; OursGolangContainers andMysqlThe container was successfully run in association, and it was completed:)



Although the application can already run

But if you are rightGolangAndDockerWith some understanding, I hope you can think of at least 2 questions

  • Why?gin-blog-dockerTaking up so much space? (availabledocker ps -as | grep gin-blog-dockerView)
  • MysqlWhere is the data stored when the container is directly used like this?

Create a Super Small Golang Mirror

Q: First question, why is the mirror volume so large?

A:FROM golang:latestIt was the authorities who pulled the strings.golangMirroring, including Golang’s compilation and running environment, plus a bunch of GCC and build tools, is quite complete.

This is problematic.We can compile it off-site in the Golang container.We don’t need those things at all, we just need an environment that can run executable files.

Build Scratch Mirror

Scratch image, simple, compact, basically an empty image

FROM scratch


CMD ["./go-gin-example"]
CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o go-gin-example .

Compiled executable files rely on some libraries and are dynamically linked. Because what is used here isscratchMirror, it is an empty mirror, so we need to statically link the generated executable file to the library on which it depends.

$ docker build -t gin-blog-docker-scratch .
Sending build context to Docker daemon 133.1 MB
Step 1/5 : FROM scratch
Step 2/5 : WORKDIR $GOPATH/src/
 ---> Using cache
 ---> ee07e166a638
Step 3/5 : COPY . $GOPATH/src/
 ---> 1489a0693d51
Removing intermediate container e3e9efc0fe4d
Step 4/5 : EXPOSE 8000
 ---> Running in b5630de5544a
 ---> 6993e9f8c944
Removing intermediate container b5630de5544a
Step 5/5 : CMD ./go-gin-example
 ---> Running in eebc0d8628ae
 ---> 5310bebeb86a
Removing intermediate container eebc0d8628ae
Successfully built 5310bebeb86a

Note that assuming your Golang application does not rely on any configuration files, you can directly copy the executable files into it, and you don’t have to care about anything else.

There are several solutions here

  • Rely on File to Manage Mount Uniformly
  • Go-bindata

So here ifThe problem of file dependence is solvedAfter that, there is no need to give the catalog toCOPYGo in

$ docker run --link mysql:mysql -p 8000:8000 gin-blog-docker-scratch
[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
 - using env:    export GIN_MODE=release
 - using code:    gin.SetMode(gin.ReleaseMode)

[GIN-debug] GET    /auth                     --> (3 handlers)

After successful operation, the program also receives the request normally.

Next, let’s look at the occupation size and execute it.docker ps -asCommand

$ docker ps -as
CONTAINER ID        IMAGE                     COMMAND                  ...         SIZE
9ebdba5a8445        gin-blog-docker-scratch   "./go-gin-example"       ...     0 B (virtual 132 MB)
427ee79e6857        gin-blog-docker           "./go-gin-example"       ...     0 B (virtual 946 MB)

As a result, the occupation size isScratchMirror-based container wins and achieves goal

Mysql Mount Data Volumes

If there is no interference, start one at a time.MysqlThe database is empty when the container is loaded. In addition, after the container is deleted, the data is lost (and there are all kinds of accidents), which is very bad!

Data volume

The data volume is designed to persist data. Its life cycle is independent of the container. Docker will not automatically delete the data volume after the container is deleted, and there is no mechanism such as garbage collection to process the data volume without any container reference. If you need to remove the data volume while deleting the container. Can be used when deleting containersdocker rm -vThis order

A data volume is a special directory that can be used by one or more containers. It bypasses UFS and provides many useful features:

  • Data volumes can be shared and reused between containers
  • Changes to the data volume will take effect immediately.
  • Updates to data volumes will not affect mirroring.
  • The data volume will always exist by default, even if the container is deleted.

Note: The use of data volumes is similar to the mount of directories or files under Linux. Files in directories designated as mount points in the mirror will be hidden and the mounted data volumes can be displayed.

How to mount

First, create a directory for storing data volumes; Sample directory/data/docker-mysqlAttention--nameOriginally namedmysql, you need to delete it.docker rm

$ docker run --name mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=rootroot -v /data/docker-mysql:/var/lib/mysql -d mysql

Create successfully, check directory/data/docker-mysql, the following many more database files


Next, it will be submitted to you for verification. The goal is to create some test tables and data, then delete the current container and recreate the container. The database data will still exist (of course, the data volumes will point to the same point)

I have verified it, and you?


This series of sample codes

This series of catalogues