green-code-initiative / ecoCode-challenge

Emboard in the hackhatons serie for improving ecoCode
3 stars 4 forks source link

[Hackathon 2024][Gadolinium][Docker] Use Docker multi-stage build #109

Open MP-Aubay opened 1 month ago

MP-Aubay commented 1 month ago

(Existing rule in draft : https://github.com/green-code-initiative/ecoCode-common/issues/44)

Rule title

Use Docker multi-stage build

Language and platform

Docker

Rule description

Multi-stage builds let you reduce the size of your final image, by creating a cleaner separation between the building of your image and the final output. Split your Dockerfile instructions into distinct stages to make sure that the resulting output only contains the files that's needed to run the application. https://docs.docker.com/develop/develop-images/guidelines/

Noncompliant Code Example

For NodeJS :

FROM node:lts

COPY package*.json ./

RUN npm install

COPY . .

RUN npm run build

CMD ["node", "index.js"]

For Maven :

FROM maven:3.9-eclipse-temurin-17

COPY ./ ./

RUN mvn clean package

CMD ["java", "-jar", "target/app.jar"]

For C :

FROM gcc

COPY hello.c .

RUN gcc -o hello hello.c

CMD ["./hello"]

For GO :

FROM golang

COPY hello.go .

RUN go build hello.go

CMD ["./hello"]

Compliant Solution

For NodeJS :

FROM node:lts AS builder

COPY package*.json ./

RUN npm install

COPY . .

RUN npm run build

FROM node:lts-alpine

COPY package*.json ./

RUN npm install --only=production

COPY --from=builder /dist ./

CMD ["node", "index.js"]

For Maven :

FROM maven:3.9-eclipse-temurin-17 AS builder

COPY ./ ./

RUN mvn clean package

FROM eclipse-temurin:17-alpine

COPY --from=builder /target/app.jar ./app.jar

CMD ["java", "-jar", "app.jar"]

For C :

FROM gcc AS builder

COPY hello.c .

RUN gcc -o hello hello.c

FROM ubuntu

COPY --from=builder hello .

CMD ["./hello"]

For GO :

FROM golang AS builder

WORKDIR /src

COPY hello.go .

RUN go build hello.go

FROM ubuntu

COPY --from=builder /src/hello .

CMD ["./hello"]

Rule short description

Using build commands will produce files not needed to run the application, you should use Docker multi-stage build.

Rule justification

Using Docker multi-stage build can reduce the size image and can reduce energy consumption.

Why it matters:

Official documentation : https://docs.docker.com/develop/develop-images/guidelines/ https://docs.docker.com/build/building/multi-stage/

Scientific article : https://assets-eu.researchsquare.com/files/rs-3276965/v1_covered_8dc408b5-6997-486a-89c8-a5c66fddf60e.pdf?c=1693976849

Measurement (from the scientific article) : Docker Images with Original Image size Obtained Image size Image size Reduced
Being lazy couch potatoes 1.47GB 1.47GB 0%
Using multistage builds 1.47GB 41.6MB 97.17%

Severity / Remediation Cost

Severity : Major, using build commands without multi-stage build will increase the image size, sometimes by ten or more.

Remediation cost : Medium, user need to understand how multi-stage build works and modify the Dockerfile.

Implementation principle

The general idea is to check in Dockerfile the presence of RUN command with build commands, for example mvn clean package or gcc -o hello hello.c. If there is such commands after the last FROM then the rule should break.

This rule will evolve as we add new build commands to check.

Identified commands : mvn * npm * gcc * go *