{"id":4399,"date":"2024-12-14T12:00:51","date_gmt":"2024-12-14T05:00:51","guid":{"rendered":"https:\/\/www.marketenterprise.vn\/blog\/?p=4399"},"modified":"2024-12-14T12:13:27","modified_gmt":"2024-12-14T05:13:27","slug":"optimize-docker-image","status":"publish","type":"post","link":"https:\/\/www.marketenterprise.vn\/blog\/optimize-docker-image.html","title":{"rendered":"7 Ultimate Hacks to Optimize Docker Image Size"},"content":{"rendered":"<pre><\/pre>\n<p>&nbsp;<\/p>\n<h2><b>1. Benefits of optimizing Docker image size <\/b><\/h2>\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Reduced build and deploy time<\/b><span style=\"font-weight: 400;\">: Lightweight Docker images make the build and deploy processes faster, saving time in the CI\/CD pipeline..<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Storage savings<\/b><span style=\"font-weight: 400;\">: Optimized Docker images consume fewer storage resources, reducing storage costs on cloud or local systems.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Improved performance<\/b><span style=\"font-weight: 400;\">: Smaller images load faster, reducing latency when pulling\/pushing images between environments.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Enhanced security<\/b><span>: Minimal Docker images with fewer unnecessary dependencies reduce the potential attack surface.<\/span><\/li>\n<\/ul>\n<h2><b>2. Ways to optimize Docker image size<\/b><\/h2>\n<h3><b>2.1. Use a lightweight base image<\/b><\/h3>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/mevn-public.s3-ap-southeast-1.amazonaws.com\/marketenterprise.vn\/wp-images\/2024\/12\/05133358\/pic2.webp\" alt=\"\" width=\"1024\" height=\"1024\" class=\"size-full wp-image-4445 aligncenter\" srcset=\"https:\/\/mevn-public.s3-ap-southeast-1.amazonaws.com\/marketenterprise.vn\/wp-images\/2024\/12\/05133358\/pic2.webp 1024w, https:\/\/mevn-public.s3-ap-southeast-1.amazonaws.com\/marketenterprise.vn\/wp-images\/2024\/12\/05133358\/pic2-300x300.webp 300w, https:\/\/mevn-public.s3-ap-southeast-1.amazonaws.com\/marketenterprise.vn\/wp-images\/2024\/12\/05133358\/pic2-90x90.webp 90w, https:\/\/mevn-public.s3-ap-southeast-1.amazonaws.com\/marketenterprise.vn\/wp-images\/2024\/12\/05133358\/pic2-768x768.webp 768w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/p>\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Method<\/b><span style=\"font-weight: 400;\">: Choose a small base image like <span style=\"color: #008000;\">Alpine<\/span> instead of <span style=\"color: #008000;\">Ubuntu<\/span> or <span style=\"color: #008000;\">Debian<\/span><\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Example<\/b><span>:<\/span><\/li>\n<\/ul>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"dockerfile\"># Dockerfile s\u1eed d\u1ee5ng base image Alpine\r\nFROM node:18-alpine\r\n\r\nWORKDIR \/app\r\n\r\nCOPY package.json yarn.lock .\/\r\nRUN yarn install --production\r\n\r\nCOPY . .\r\n\r\nCMD [\"node\", \"index.js\"]\r\n<\/pre>\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Explain<\/b><span style=\"font-weight: 400;\">:<\/span>\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"2\"><span style=\"color: #008000;\"><b>node:18-alpine<\/b><\/span><span style=\"font-weight: 400;\">: This is a Node.js version built on Alpine Linux, which is much smaller than <span style=\"color: #008000;\">node:18<\/span>.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"2\"><span style=\"color: #008000;\"><b>yarn install &#8211;production<\/b><\/span><span>: Only install production dependencies, skipping devDependencies to reduce image size.<\/span><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<h3><b>2.2. Use Multi-Stage Build<\/b><\/h3>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/mevn-public.s3-ap-southeast-1.amazonaws.com\/marketenterprise.vn\/wp-images\/2024\/12\/05133400\/pic3.webp\" alt=\"\" width=\"1024\" height=\"1024\" class=\"size-full wp-image-4446 aligncenter\" srcset=\"https:\/\/mevn-public.s3-ap-southeast-1.amazonaws.com\/marketenterprise.vn\/wp-images\/2024\/12\/05133400\/pic3.webp 1024w, https:\/\/mevn-public.s3-ap-southeast-1.amazonaws.com\/marketenterprise.vn\/wp-images\/2024\/12\/05133400\/pic3-300x300.webp 300w, https:\/\/mevn-public.s3-ap-southeast-1.amazonaws.com\/marketenterprise.vn\/wp-images\/2024\/12\/05133400\/pic3-90x90.webp 90w, https:\/\/mevn-public.s3-ap-southeast-1.amazonaws.com\/marketenterprise.vn\/wp-images\/2024\/12\/05133400\/pic3-768x768.webp 768w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/p>\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Method<\/b><span style=\"font-weight: 400;\">: Use multi-stage builds to remove unnecessary files and dependencies from the production image.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Example<\/b><span>:<\/span><\/li>\n<\/ul>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"dockerfile\"># Stage 1: Build application\r\nFROM node:18 as builder\r\n\r\nWORKDIR \/app\r\nCOPY package.json yarn.lock .\/\r\nRUN yarn install\r\nCOPY . .\r\nRUN yarn build\r\n\r\n# Stage 2: Create production image\r\nFROM nginx:alpine\r\n\r\nCOPY --from=builder \/app\/build \/usr\/share\/nginx\/html\r\n\r\nEXPOSE 80\r\nCMD [\"nginx\", \"-g\", \"daemon off;\"]\r\n<\/pre>\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Explain<\/b><span style=\"font-weight: 400;\">:<\/span>\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"2\"><span style=\"color: #008000;\"><b>FROM node:18 as builder<\/b><\/span><span style=\"font-weight: 400;\">: The first stage is used for building the code, and it can contain multiple build dependencies and tools.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"2\"><span style=\"color: #008000;\"><b>COPY &#8211;from=builder<\/b><\/span><span>: Only copy necessary artifacts from the build stage to the production image, omitting unnecessary files.<\/span><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<h3><b>2.3. Removing unnecessary files from the image<\/b><\/h3>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/mevn-public.s3-ap-southeast-1.amazonaws.com\/marketenterprise.vn\/wp-images\/2024\/12\/05133404\/pic4-scaled.webp\" alt=\"\" width=\"1366\" height=\"781\" class=\"size-full wp-image-4447 aligncenter\" srcset=\"https:\/\/mevn-public.s3-ap-southeast-1.amazonaws.com\/marketenterprise.vn\/wp-images\/2024\/12\/05133404\/pic4-scaled.webp 1366w, https:\/\/mevn-public.s3-ap-southeast-1.amazonaws.com\/marketenterprise.vn\/wp-images\/2024\/12\/05133404\/pic4-300x171.webp 300w, https:\/\/mevn-public.s3-ap-southeast-1.amazonaws.com\/marketenterprise.vn\/wp-images\/2024\/12\/05133404\/pic4-1024x585.webp 1024w, https:\/\/mevn-public.s3-ap-southeast-1.amazonaws.com\/marketenterprise.vn\/wp-images\/2024\/12\/05133404\/pic4-768x439.webp 768w, https:\/\/mevn-public.s3-ap-southeast-1.amazonaws.com\/marketenterprise.vn\/wp-images\/2024\/12\/05133404\/pic4-1536x878.webp 1536w, https:\/\/mevn-public.s3-ap-southeast-1.amazonaws.com\/marketenterprise.vn\/wp-images\/2024\/12\/05133404\/pic4-1568x896.webp 1568w\" sizes=\"auto, (max-width: 1366px) 100vw, 1366px\" \/><\/p>\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Method<\/b><span style=\"font-weight: 400;\">: Using commands like <span style=\"color: #008000;\">rm<\/span> to remove cache or unnecessary files after installing dependencies<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Example<\/b><span>:<\/span><\/li>\n<\/ul>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"dockerfile\">FROM python:3.10-slim\r\n\r\nWORKDIR \/app\r\n\r\nCOPY requirements.txt .\/\r\nRUN pip install --no-cache-dir -r requirements.txt\r\n\r\nCOPY . .\r\n\r\nCMD [\"python\", \"app.py\"]\r\n<\/pre>\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Explain<\/b><span style=\"font-weight: 400;\">:<\/span>\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"2\"><span style=\"color: #008000;\"><b>&#8211;no-cache-dir<\/b><\/span><span style=\"font-weight: 400;\">: Avoid saving <span style=\"color: #008000;\">pip<\/span> cache after installing dependencies<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"2\"><span style=\"color: #008000;\"><b>slim<\/b><\/span><span>: Lightweight base image, reducing unnecessary tools.<\/span><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<h3><b>2.4. Use <\/b><b>.dockerignore<\/b><\/h3>\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Method<\/b><span style=\"font-weight: 400;\">: Using a <span style=\"color: #008000;\">.dockerignore<\/span> file to exclude unnecessary files from the build context is a common practice to optimize Docker image size.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Example<\/b><span>:<\/span><\/li>\n<\/ul>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"dockerfile\"># .dockerignore\r\nnode_modules\r\n.env\r\ndist\r\nlogs\r\n<\/pre>\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Explain<\/b><span style=\"font-weight: 400;\">: Excluding directories like <span style=\"color: #008000;\">node_modules, logs<\/span>, or temporary files that are not needed reduces the build context size and final image size.<\/span><\/li>\n<\/ul>\n<h3><b>2.5. Reducing the number of layers in a Dockerfile<\/b><\/h3>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/mevn-public.s3-ap-southeast-1.amazonaws.com\/marketenterprise.vn\/wp-images\/2024\/12\/05133225\/pic5.png\" alt=\"\" width=\"675\" height=\"469\" class=\"size-full wp-image-4442 aligncenter\" srcset=\"https:\/\/mevn-public.s3-ap-southeast-1.amazonaws.com\/marketenterprise.vn\/wp-images\/2024\/12\/05133225\/pic5.png 675w, https:\/\/mevn-public.s3-ap-southeast-1.amazonaws.com\/marketenterprise.vn\/wp-images\/2024\/12\/05133225\/pic5-300x208.png 300w\" sizes=\"auto, (max-width: 675px) 100vw, 675px\" \/><\/p>\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Method<\/b><span style=\"font-weight: 400;\">: Combining multiple <span style=\"color: #008000;\">RUN<\/span> instructions into a single line to reduce the number of layers created.<\/span><span style=\"font-weight: 400;\">.<\/span>\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Example<\/b><span>:<\/span><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"dockerfile\">RUN apt-get update &amp;&amp; apt-get install -y \\\r\n    curl \\\r\n    vim \\\r\n &amp;&amp; apt-get clean \\\r\n &amp;&amp; rm -rf \/var\/lib\/apt\/lists\/*<\/pre>\n<ul>\n<li style=\"list-style-type: none;\">\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Explain<\/b><span style=\"font-weight: 400;\">: Combining multiple <span style=\"color: #008000;\">RUN<\/span> instructions into a single line to create a single layer, making the image more streamlined.<\/span><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<h3><b>2.6. Use Docker BuildKit<\/b><\/h3>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/mevn-public.s3-ap-southeast-1.amazonaws.com\/marketenterprise.vn\/wp-images\/2024\/12\/05133227\/pic6.png\" alt=\"\" width=\"583\" height=\"369\" class=\"size-full wp-image-4443 aligncenter\" srcset=\"https:\/\/mevn-public.s3-ap-southeast-1.amazonaws.com\/marketenterprise.vn\/wp-images\/2024\/12\/05133227\/pic6.png 583w, https:\/\/mevn-public.s3-ap-southeast-1.amazonaws.com\/marketenterprise.vn\/wp-images\/2024\/12\/05133227\/pic6-300x190.png 300w\" sizes=\"auto, (max-width: 583px) 100vw, 583px\" \/><\/p>\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Method: <\/b>Docker BuildKit is an improved tool that enables faster and more efficient image builds. It supports better caching, parallel builds, and several features that help reduce image size.<\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Example:<\/b><\/li>\n<\/ul>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"dockerfile\"># Enable BuildKit\r\n# In terminal: export DOCKER_BUILDKIT=1\r\n\r\n# Dockerfile\r\n# Use cache mount to optimize apt-get and reduce dependencies\r\n# Base image\r\nFROM debian:bullseye-slim\r\n\r\n# Install dependencies\r\nRUN --mount=type=cache,target=\/var\/cache\/apt \\\r\n    apt-get update &amp;&amp; apt-get install -y curl &amp;&amp; \\\r\n    apt-get clean &amp;&amp; rm -rf \/var\/lib\/apt\/lists\/*\r\n\r\nWORKDIR \/app\r\nCOPY . .\r\n\r\nCMD [\"bash\"]<\/pre>\n<ul>\n<li aria-level=\"1\">\n<h4><b>Explain:<\/b><\/h4>\n<\/li>\n<\/ul>\n<ul>\n<li style=\"list-style-type: none;\">\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"2\"><span style=\"color: #008000;\"><b>&#8211;mount=type=cache<\/b><\/span><span style=\"font-weight: 400;\">: Using BuildKit to cache files from apt-get helps reduce the need to re-download files during multiple builds.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"2\"><span style=\"color: #008000;\"><b>export DOCKER_BUILDKIT=1<\/b><\/span><span style=\"font-weight: 400;\">: Enable BuildKit when using Docker CLI.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"2\"><b>Base image <\/b><span style=\"color: #008000;\"><b>debian:bullseye-slim<\/b><\/span><span>: A lightweight version of Debian, reducing the size of Docker images.<\/span><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<h3><b>2.7. Reduce the number of dependencies<\/b><\/h3>\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"1\">\n<h4><b>Method:<\/b><span style=\"font-weight: 400;\"> Limit the number of dependencies by:<\/span><\/h4>\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"2\"><span style=\"font-weight: 400;\">Installing only necessary libraries and tools.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"2\"><span style=\"font-weight: 400;\">Removing unused libraries from the application.<\/span><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<ul>\n<li aria-level=\"1\">\n<h4><b>Example<\/b><\/h4>\n<\/li>\n<\/ul>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"dockerfile\">FROM node:18-alpine\r\n\r\nWORKDIR \/app\r\n\r\n# Copy ch\u1ec9 c\u00e1c file c\u1ea7n thi\u1ebft\r\nCOPY package.json yarn.lock .\/\r\n\r\n# Ch\u1ec9 c\u00e0i \u0111\u1eb7t dependencies c\u1ea7n thi\u1ebft cho production\r\nRUN yarn install --production\r\n\r\nCOPY . .\r\n\r\nCMD [\"node\", \"app.js\"]<\/pre>\n<ul>\n<li aria-level=\"1\">\n<h4><b>Explain:<\/b><\/h4>\n<\/li>\n<\/ul>\n<ul>\n<li style=\"list-style-type: none;\">\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"2\"><span style=\"color: #008000;\"><b>&#8211;production<\/b><\/span><span style=\"font-weight: 400;\">: Install only production dependencies, skipping devDependencies to reduce the size.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"2\"><span style=\"color: #008000;\"><b>COPY package.json yarn.lock .\/<\/b><\/span><span> before: Helps to leverage cache when dependencies don&#8217;t change.<\/span><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<h2><b>3. Summary<\/b><\/h2>\n<p>Optimizing Docker image size not only reduces costs and improves performance but also enhances application security. Investing time in learning and applying best practices will help you work more efficiently with Docker. Always check the image size using the <em><span style=\"color: #008000;\">docker images<\/span><\/em> command and try to reduce it if necessary.<\/p>\n<h3>References<\/h3>\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><a href=\"https:\/\/docs.docker.com\/guides\/\" target=\"_blank\" rel=\"noopener\"><span style=\"font-weight: 400;\">Docker Official Documentation<\/span><\/a><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><a href=\"https:\/\/docs.docker.com\/build\/building\/best-practices\/\" target=\"_blank\" rel=\"noopener\"><span style=\"font-weight: 400;\">Best practices for writing Dockerfiles<\/span><\/a><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><a href=\"https:\/\/docs.docker.com\/build\/building\/multi-stage\/\" target=\"_blank\" rel=\"noopener\"><span style=\"font-weight: 400;\">Multi-Stage Builds Guide<\/span><\/a><\/li>\n<\/ul>\n<h3>Related articles<\/h3>\n<ul>\n<li><a href=\"https:\/\/www.marketenterprise.vn\/blog\/docker-la-gi.html\">Docker l\u00e0 g\u00ec ?<\/a><\/li>\n<li><a href=\"https:\/\/www.marketenterprise.vn\/blog\/chay-flask-python-tren-docker.html\">2 b\u01b0\u1edbc \u0111\u01a1n gi\u1ea3n \u0111\u1ec3 ch\u1ea1y m\u1ed9t ch\u01b0\u01a1ng tr\u00ecnh Flask Python tr\u00ean docker<\/a><\/li>\n<li><a href=\"https:\/\/www.marketenterprise.vn\/blog\/rest-api-voi-golang-gin-minio.html\">Rest API v\u1edbi Golang, Gin, MinIO v\u00e0 Docker<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Guide to optimizing Docker image size: reduce size, improve CI\/CD performance, and save storage resources efficiently.<\/p>\n","protected":false},"author":46,"featured_media":4444,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[28,196,197],"class_list":["post-4399","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-technology","tag-docker","tag-docker-image","tag-optimize-docker-image"],"_links":{"self":[{"href":"https:\/\/www.marketenterprise.vn\/blog\/wp-json\/wp\/v2\/posts\/4399","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.marketenterprise.vn\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.marketenterprise.vn\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.marketenterprise.vn\/blog\/wp-json\/wp\/v2\/users\/46"}],"replies":[{"embeddable":true,"href":"https:\/\/www.marketenterprise.vn\/blog\/wp-json\/wp\/v2\/comments?post=4399"}],"version-history":[{"count":0,"href":"https:\/\/www.marketenterprise.vn\/blog\/wp-json\/wp\/v2\/posts\/4399\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.marketenterprise.vn\/blog\/wp-json\/wp\/v2\/media\/4444"}],"wp:attachment":[{"href":"https:\/\/www.marketenterprise.vn\/blog\/wp-json\/wp\/v2\/media?parent=4399"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.marketenterprise.vn\/blog\/wp-json\/wp\/v2\/categories?post=4399"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.marketenterprise.vn\/blog\/wp-json\/wp\/v2\/tags?post=4399"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}