Deploying Golang Applications to Docker
- You need to install it before you start.
docker, with a good mirror source
- This chapter source code in
f-20180324-dockerOn the branch
- Starting from this chapter, the project catalog is based on
go-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 project
dockerFor the required processing and writing, each headline is a step outline.
I. writing Dockerfile
go-gin-exampleThe project root directory creates a Dockerfile file and writes the contents
FROM golang:latest WORKDIR $GOPATH/src/github.com/EDDYCJY/go-gin-example COPY . $GOPATH/src/github.com/EDDYCJY/go-gin-example RUN go build . EXPOSE 8000 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
go buildAfter compiling, set the container launcher to
./go-gin-example, which is the executable we compiled
pay attention to
dockerCompiled 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 is
WORKDIR< working directory path >
WORKDIRInstructions 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
RUN< command >
The format is
EXPOSE< 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 is
docker run -PWhen, will automatically random mapping
ENTRYPOINTThe format and
RUNInstruction formats are the same, divided into two formats
ENTRYPOINT [ "curl", "-s", "http://ip.cn" ]
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 is
.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/github.com/EDDYCJY/go-gin-example ---> 56294f978c5d Removing intermediate container e112997b995d Step 3/6 : COPY . $GOPATH/src/github.com/EDDYCJY/go-gin-example ---> 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 them
gin-blog-dockerDoes the mirror exist
$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE gin-blog-docker latest d8a109c7697c About a minute ago 946 MB docker.io/golang latest d632bbfe5767 8 days ago 779 MB ...
Four, create and run a new container
docker run -p 8000:8000 gin-blog-docker
$ docker run -p 8000:8000 gin-blog-docker dial tcp 127.0.0.1:3306: 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 127.0.0.1:3306: connect: connection refused
We studied and found that
MysqlWe will solve this problem in the second item.
First, pull the mirror image
DockerPublic warehouse of
MySQLMirroring (a mirror image is recommended in China)
$ docker pull mysql
Second, create and run a new container
MysqlContainer, and set the return container ID after successful execution
$ docker run --name mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=rootroot -d mysql 8c86ac986da4922492934b6fe074254c9165b8ee3e184d29865921b0fef29e64
MysqlShould 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 Different
tagNew Mirror of
Delete the original problematic mirror image,
-fIs forced deletion and its associated status
If not implemented
-f, you need to perform
docker ps -aThe associated container is found and
rmRelieve 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 file
conf/app.ini, the content is modified to
#debug or release RUN_MODE = debug [app] PAGE_SIZE = 10 JWT_SECRET = 233 [server] HTTP_PORT = 8000 READ_TIMEOUT = 60 WRITE_TIMEOUT = 60 [database] TYPE = mysql USER = root PASSWORD = rootroot HOST = mysql:3306 NAME = blog TABLE_PREFIX = blog_
Third, rebuild the mirror image
Repeat the previous steps to return to
gin-blogUnder the project root directory ofcarry out
docker build -t gin-blog-docker .
Four, create and run a new container
Q: We need to transfer
MysqlContainers are linked, so what do we need to do?
A: add order
MysqlContainer 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.
docker 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; Ours
MysqlThe container was successfully run in association, and it was completed:)
Although the application can already run
But if you are right
DockerWith some understanding, I hope you can think of at least 2 questions
gin-blog-dockerTaking up so much space? (available
docker 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?
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 WORKDIR $GOPATH/src/github.com/EDDYCJY/go-gin-example COPY . $GOPATH/src/github.com/EDDYCJY/go-gin-example EXPOSE 8000 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 is
scratchMirror, 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/github.com/EDDYCJY/go-gin-example ---> Using cache ---> ee07e166a638 Step 3/5 : COPY . $GOPATH/src/github.com/EDDYCJY/go-gin-example ---> 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
So here ifThe problem of file dependence is solvedAfter that, there is no need to give the catalog to
$ 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 --> github.com/EDDYCJY/go-gin-example/routers/api.GetAuth (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 is
ScratchMirror-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!
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 containers
docker 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
mysql, you need to delete it.
$ docker run --name mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=rootroot -v /data/docker-mysql:/var/lib/mysql -d mysql 54611dbcd62eca33fb320f3f624c7941f15697d998f40b24ee535a1acf93ae72
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
- Serial One Golang Introduction and Environmental Installation
- Serialized 2 to build Blog API’s (1)
- Serial 3 to build Blog API’s (2)
- Serial 4 to build Blog API’s (3)
- Serial 5 Use JWT for Identity Verification
- Serial 6 Write a Simple File Log
- Serial Seven Golang Gracefully Restart HTTP Service
- Serial 8 Add Swagger to It
- Serial 9 Deploying Golang Applications to Docker
- Serial Ten Customized GORM Callbacks
- Serial Eleven Cron Scheduled Tasks
- Serial 12 Optimizing Configuration Structure and Realizing Picture Upload
- Serialization 13 Optimize Your Application Structure and Implement Redis Cache
- Serial 14 Realize Export and Import into Excel
- Serial 15 Generate Two-dimensional Code and Merge Posters
- Serial 16 Draw Text on Pictures
- Serial 17 Deploying Go Applications with Nginx
- Cross-compilation of safari Golang
- Please get started with Makefile