{"componentChunkName":"component---src-templates-blog-js","path":"/blog/multi-stage-docker-build","result":{"data":{"contentfulBlogPost":{"title":"Multi-stage Docker Builds","publishedDate":"January 9th, 2021","body":{"json":{"nodeType":"document","data":{},"content":[{"nodeType":"paragraph","content":[{"nodeType":"text","value":"Hello everyone, today I'll try to explain how to create multi stage Docker builds in order to decrease build size with Dockerfile on a small Go application and latest GoLang image from DockerHub.","marks":[],"data":{}}],"data":{}},{"nodeType":"hr","content":[],"data":{}},{"nodeType":"paragraph","content":[{"nodeType":"text","value":"Through this tutorial I won't publish any code snippets directly, I'll instead give you a ","marks":[],"data":{}},{"nodeType":"hyperlink","content":[{"nodeType":"text","value":"repo","marks":[],"data":{}}],"data":{"uri":"https://github.com/eren23/go-docker-multi-stage-blog"}},{"nodeType":"text","value":" to copy and paste.","marks":[],"data":{}}],"data":{}},{"nodeType":"paragraph","content":[{"nodeType":"text","value":"First we'll create a really basic Go webserver using Mux package. \"Package ","marks":[],"data":{}},{"nodeType":"text","value":"gorilla/mux","marks":[{"type":"code"}],"data":{}},{"nodeType":"text","value":" implements a request router and dispatcher for matching incoming requests to their respective handler.\" from their GitHub ","marks":[],"data":{}},{"nodeType":"hyperlink","content":[{"nodeType":"text","value":"page","marks":[],"data":{}}],"data":{"uri":"https://github.com/gorilla/mux"}},{"nodeType":"text","value":". You can also learn how to install that package on your local from the link.","marks":[],"data":{}}],"data":{}},{"nodeType":"paragraph","content":[{"nodeType":"text","value":"After that we need to create a main.go file with the following content.","marks":[],"data":{}}],"data":{}},{"nodeType":"embedded-asset-block","content":[],"data":{"target":{"sys":{"space":{"sys":{"type":"Link","linkType":"Space","id":"qv0hcw26u3ts","contentful_id":"qv0hcw26u3ts"}},"id":"c3DRjLWfAkm0XpFvtQP3r5o","type":"Asset","createdAt":"2021-01-09T15:46:01.528Z","updatedAt":"2021-01-09T15:46:01.528Z","environment":{"sys":{"id":"master","type":"Link","linkType":"Environment","contentful_id":"master"}},"revision":1,"contentful_id":"3DRjLWfAkm0XpFvtQP3r5o"},"fields":{"title":{"en-US":"docker-multistage-maingo"},"file":{"en-US":{"url":"//images.ctfassets.net/qv0hcw26u3ts/3DRjLWfAkm0XpFvtQP3r5o/1b6eb62410c592603b41b5597ff33744/Screen_Shot_2021-01-09_at_16.45.13.png","details":{"size":105979,"image":{"width":820,"height":692}},"fileName":"Screen Shot 2021-01-09 at 16.45.13.png","contentType":"image/png"}}}}}},{"nodeType":"paragraph","content":[{"nodeType":"text","value":"","marks":[],"data":{}}],"data":{}},{"nodeType":"hr","content":[],"data":{}},{"nodeType":"paragraph","content":[{"nodeType":"text","value":"After we create our main.go we can go ahead and initialize a go module with the command:","marks":[],"data":{}}],"data":{}},{"nodeType":"paragraph","content":[{"nodeType":"text","value":"go mod init (nameselectionforappofyourchoice)","marks":[{"type":"code"}],"data":{}}],"data":{}},{"nodeType":"paragraph","content":[{"nodeType":"text","value":"Then we can check if it the server is up by running our application with the command:","marks":[],"data":{}}],"data":{}},{"nodeType":"paragraph","content":[{"nodeType":"text","value":" go run .","marks":[],"data":{}}],"data":{}},{"nodeType":"paragraph","content":[{"nodeType":"text","value":"Then we should quickly create a Dockerfile in same directory and the final look of our project should be like this one now.","marks":[{"type":"code"}],"data":{}}],"data":{}},{"nodeType":"embedded-asset-block","content":[],"data":{"target":{"sys":{"space":{"sys":{"type":"Link","linkType":"Space","id":"qv0hcw26u3ts","contentful_id":"qv0hcw26u3ts"}},"id":"c4FOuIV33RHdr9CfquvHtSF","type":"Asset","createdAt":"2021-01-09T15:40:30.319Z","updatedAt":"2021-01-09T15:40:30.319Z","environment":{"sys":{"id":"master","type":"Link","linkType":"Environment","contentful_id":"master"}},"revision":1,"contentful_id":"4FOuIV33RHdr9CfquvHtSF"},"fields":{"title":{"en-US":"multistage-docker-file-structure"},"file":{"en-US":{"url":"//images.ctfassets.net/qv0hcw26u3ts/4FOuIV33RHdr9CfquvHtSF/5cf0b96b21e88e512e6add223ec8956e/Screen_Shot_2021-01-09_at_16.39.47.png","details":{"size":16942,"image":{"width":356,"height":210}},"fileName":"Screen Shot 2021-01-09 at 16.39.47.png","contentType":"image/png"}}}}}},{"nodeType":"hr","content":[],"data":{}},{"nodeType":"paragraph","content":[{"nodeType":"text","value":"Writing our Dockerfile is a little bit more tricky but I'll try to explain each step.","marks":[],"data":{}}],"data":{}},{"nodeType":"embedded-asset-block","content":[],"data":{"target":{"sys":{"space":{"sys":{"type":"Link","linkType":"Space","id":"qv0hcw26u3ts","contentful_id":"qv0hcw26u3ts"}},"id":"c2MOtmjVKVDny01G1K0LqXw","type":"Asset","createdAt":"2021-01-09T16:04:48.874Z","updatedAt":"2021-01-09T16:04:48.874Z","environment":{"sys":{"id":"master","type":"Link","linkType":"Environment","contentful_id":"master"}},"revision":1,"contentful_id":"2MOtmjVKVDny01G1K0LqXw"},"fields":{"title":{"en-US":"go-multi-stage-docker-build"},"file":{"en-US":{"url":"//images.ctfassets.net/qv0hcw26u3ts/2MOtmjVKVDny01G1K0LqXw/b986e615d05cab642bedbdc35ec46f6c/Screen_Shot_2021-01-09_at_17.03.59.png","details":{"size":47847,"image":{"width":566,"height":308}},"fileName":"Screen Shot 2021-01-09 at 17.03.59.png","contentType":"image/png"}}}}}},{"nodeType":"ordered-list","content":[{"nodeType":"list-item","content":[{"nodeType":"paragraph","content":[{"nodeType":"text","value":"We pull golang image with a specific version from DockerHub.","marks":[],"data":{}}],"data":{}}],"data":{}},{"nodeType":"list-item","content":[{"nodeType":"paragraph","content":[{"nodeType":"text","value":"We create a directory for ourselves in our container.","marks":[],"data":{}}],"data":{}}],"data":{}},{"nodeType":"list-item","content":[{"nodeType":"paragraph","content":[{"nodeType":"text","value":"We copy go.sum and go.mod files to our directory from the line above.","marks":[],"data":{}}],"data":{}}],"data":{}},{"nodeType":"list-item","content":[{"nodeType":"paragraph","content":[{"nodeType":"text","value":"We download our dependencies.","marks":[],"data":{}}],"data":{}}],"data":{}},{"nodeType":"list-item","content":[{"nodeType":"paragraph","content":[{"nodeType":"text","value":"We copy everything from our current directory to our directory in container.","marks":[],"data":{}}],"data":{}}],"data":{}},{"nodeType":"list-item","content":[{"nodeType":"paragraph","content":[{"nodeType":"text","value":"We should run go build in order to get a statically compiled go binary. (Actually all we want to do in this tutorial is to use a statically compiled Go application and with that binary in our hands we can run it even in a smaller Docker image like Alpine with no real ability of compiling a Go application.) CGO_ENABLED=0 for static compile and -o flag indicates the output folder.","marks":[],"data":{}}],"data":{}}],"data":{}},{"nodeType":"list-item","content":[{"nodeType":"paragraph","content":[{"nodeType":"text","value":"We pull another image called Alpine from DockerHub with a smaller build size.","marks":[],"data":{}}],"data":{}}],"data":{}},{"nodeType":"list-item","content":[{"nodeType":"paragraph","content":[{"nodeType":"text","value":"We copy /bin/app folder from our older stage to /bin/app folder in new image.","marks":[],"data":{}}],"data":{}}],"data":{}},{"nodeType":"list-item","content":[{"nodeType":"paragraph","content":[{"nodeType":"text","value":"We define /bin/app as our entrypoint","marks":[],"data":{}}],"data":{}}],"data":{}}],"data":{}},{"nodeType":"paragraph","content":[{"nodeType":"text","value":"We are good to go now. We can build and run our container with the following commands:","marks":[],"data":{}}],"data":{}},{"nodeType":"paragraph","content":[{"nodeType":"text","value":"docker build -t <tagselectionofyourchoice>","marks":[{"type":"code"}],"data":{}}],"data":{}},{"nodeType":"paragraph","content":[{"nodeType":"text","value":"docker run -p 5000:8080 <tagselectionofyourchoice> ","marks":[{"type":"code"}],"data":{}}],"data":{}},{"nodeType":"paragraph","content":[{"nodeType":"text","value":"## Opening a port from our Go app 8080 to our local port 5000.","marks":[{"type":"code"}],"data":{}}],"data":{}},{"nodeType":"hr","content":[],"data":{}},{"nodeType":"embedded-asset-block","content":[],"data":{"target":{"sys":{"space":{"sys":{"type":"Link","linkType":"Space","id":"qv0hcw26u3ts","contentful_id":"qv0hcw26u3ts"}},"id":"c4uXX4hjKjpITEWGbgGnO6j","type":"Asset","createdAt":"2021-01-09T16:31:16.276Z","updatedAt":"2021-01-09T16:31:16.276Z","environment":{"sys":{"id":"master","type":"Link","linkType":"Environment","contentful_id":"master"}},"revision":1,"contentful_id":"4uXX4hjKjpITEWGbgGnO6j"},"fields":{"title":{"en-US":"multi-stage-docker-app-up"},"file":{"en-US":{"url":"//images.ctfassets.net/qv0hcw26u3ts/4uXX4hjKjpITEWGbgGnO6j/13a1729faf015ab0e226e0ca49941835/Screen_Shot_2021-01-09_at_17.30.51.png","details":{"size":15677,"image":{"width":676,"height":164}},"fileName":"Screen Shot 2021-01-09 at 17.30.51.png","contentType":"image/png"}}}}}},{"nodeType":"paragraph","content":[{"nodeType":"text","value":"Now our Dockerized app is up at port 5000. ","marks":[],"data":{}}],"data":{}},{"nodeType":"embedded-asset-block","content":[],"data":{"target":{"sys":{"space":{"sys":{"type":"Link","linkType":"Space","id":"qv0hcw26u3ts","contentful_id":"qv0hcw26u3ts"}},"id":"c3mhvYcAtV4u9ernr1r8WYo","type":"Asset","createdAt":"2021-01-09T16:41:21.575Z","updatedAt":"2021-01-09T16:41:21.575Z","environment":{"sys":{"id":"master","type":"Link","linkType":"Environment","contentful_id":"master"}},"revision":1,"contentful_id":"3mhvYcAtV4u9ernr1r8WYo"},"fields":{"title":{"en-US":"image-size-reduced"},"file":{"en-US":{"url":"//images.ctfassets.net/qv0hcw26u3ts/3mhvYcAtV4u9ernr1r8WYo/0946fc0174d6fda6e7461dab3ffbaff7/Screen_Shot_2021-01-09_at_17.40.59.png","details":{"size":16176,"image":{"width":1296,"height":26}},"fileName":"Screen Shot 2021-01-09 at 17.40.59.png","contentType":"image/png"}}}}}},{"nodeType":"paragraph","content":[{"nodeType":"text","value":"Now we as we can see our container is fully functional yet image size is significantly smaller. I will not share another picture for it but original Golang image usually takes around 900MB of space alone. This is thanks to statica compiling abilities of Golang.","marks":[],"data":{}}],"data":{}},{"nodeType":"hr","content":[],"data":{}},{"nodeType":"paragraph","content":[{"nodeType":"text","value":"I hope that tutorial can help you. I'll see you in the next blog posts :).","marks":[],"data":{}}],"data":{}},{"nodeType":"paragraph","content":[{"nodeType":"text","value":"","marks":[{"type":"code"}],"data":{}}],"data":{}},{"nodeType":"paragraph","content":[{"nodeType":"text","value":"","marks":[],"data":{}}],"data":{}}]}}}},"pageContext":{"slug":"multi-stage-docker-build"}}}