SlideShare une entreprise Scribd logo
1  sur  96
Télécharger pour lire hors ligne
Laissez tomber vos Dockerfile,
adoptez un Buildpack !
Julien Wittouck - @CodeKaio
1
Vous êtes au bon endroit si
Vous êtes un·e Dev
Vous être un·e Ops
Vous faites souvent joujou avec Docker !
2
Exécuter une application dans un
container, c'est facile.
Un Dockerfile øet hop Æ, en prod
!
3
Non
4
J'écris des (mauvais _) Dockerfile
depuis 2015
FROM node:latest
COPY . .
RUN npm install
CMD ["npm", "start"]
1
2
3
4
FROM openjdk:latest
COPY . .
CMD ["./mvnw", "spring-boot:run"]
1
2
3
5
ø Dockerfile ø Dockerfile
Salut 9
Moi c’est Julien
Freelance @CodeKaio
Associé @Ekité
Teacher @univ-lille
dSpeaker (DevFest
Lille - Sunny Tech)
ûReviewer Cloud Nord
6
Allez, on embarque !
7
Dockerfiles
8
Comment Docker construit une image ?
"Exécute" le Dockerfile
Dans des containers séparés
"SNAPSHOT" le filesystem à chaque étape pour créer les
layers
9
Le Hello World Spring Boot, selon
Docker _
www.docker.com/blog
FROM eclipse-temurin:17-jdk-focal
WORKDIR /app
COPY .mvn/ .mvn
COPY mvnw pom.xml ./
RUN ./mvnw dependency:go-offline
COPY src ./src
CMD ["./mvnw", "spring-boot:run"]
1
2
3
4
5
6
7
8
9
10
11
10
ø Dockerfile
Le Hello World Spring Boot, selon
Docker _
www.docker.com/blog
FROM eclipse-temurin:17-jdk-focal
WORKDIR /app
COPY .mvn/ .mvn
COPY mvnw pom.xml ./
RUN ./mvnw dependency:go-offline
COPY src ./src
CMD ["./mvnw", "spring-boot:run"]
1
2
3
4
5
6
7
8
9
10
11
FROM eclipse-temurin:17-jdk-focal
1
2
WORKDIR /app
3
4
COPY .mvn/ .mvn
5
COPY mvnw pom.xml ./
6
RUN ./mvnw dependency:go-offline
7
8
COPY src ./src
9
10
CMD ["./mvnw", "spring-boot:run"]
11
10.1
ø Dockerfile
Le Hello World Spring Boot, selon
Docker _
www.docker.com/blog
FROM eclipse-temurin:17-jdk-focal
WORKDIR /app
COPY .mvn/ .mvn
COPY mvnw pom.xml ./
RUN ./mvnw dependency:go-offline
COPY src ./src
CMD ["./mvnw", "spring-boot:run"]
1
2
3
4
5
6
7
8
9
10
11
FROM eclipse-temurin:17-jdk-focal
1
2
WORKDIR /app
3
4
COPY .mvn/ .mvn
5
COPY mvnw pom.xml ./
6
RUN ./mvnw dependency:go-offline
7
8
COPY src ./src
9
10
CMD ["./mvnw", "spring-boot:run"]
11
COPY .mvn/ .mvn
COPY mvnw pom.xml ./
RUN ./mvnw dependency:go-offline
FROM eclipse-temurin:17-jdk-focal
1
2
WORKDIR /app
3
4
5
6
7
8
COPY src ./src
9
10
CMD ["./mvnw", "spring-boot:run"]
11
10.2
ø Dockerfile
Le Hello World Spring Boot, selon
Docker _
www.docker.com/blog
FROM eclipse-temurin:17-jdk-focal
WORKDIR /app
COPY .mvn/ .mvn
COPY mvnw pom.xml ./
RUN ./mvnw dependency:go-offline
COPY src ./src
CMD ["./mvnw", "spring-boot:run"]
1
2
3
4
5
6
7
8
9
10
11
FROM eclipse-temurin:17-jdk-focal
1
2
WORKDIR /app
3
4
COPY .mvn/ .mvn
5
COPY mvnw pom.xml ./
6
RUN ./mvnw dependency:go-offline
7
8
COPY src ./src
9
10
CMD ["./mvnw", "spring-boot:run"]
11
COPY .mvn/ .mvn
COPY mvnw pom.xml ./
RUN ./mvnw dependency:go-offline
FROM eclipse-temurin:17-jdk-focal
1
2
WORKDIR /app
3
4
5
6
7
8
COPY src ./src
9
10
CMD ["./mvnw", "spring-boot:run"]
11
COPY src ./src
FROM eclipse-temurin:17-jdk-focal
1
2
WORKDIR /app
3
4
COPY .mvn/ .mvn
5
COPY mvnw pom.xml ./
6
RUN ./mvnw dependency:go-offline
7
8
9
10
CMD ["./mvnw", "spring-boot:run"]
11
10.3
ø Dockerfile
Le Hello World Spring Boot, selon
Docker _
www.docker.com/blog
FROM eclipse-temurin:17-jdk-focal
WORKDIR /app
COPY .mvn/ .mvn
COPY mvnw pom.xml ./
RUN ./mvnw dependency:go-offline
COPY src ./src
CMD ["./mvnw", "spring-boot:run"]
1
2
3
4
5
6
7
8
9
10
11
FROM eclipse-temurin:17-jdk-focal
1
2
WORKDIR /app
3
4
COPY .mvn/ .mvn
5
COPY mvnw pom.xml ./
6
RUN ./mvnw dependency:go-offline
7
8
COPY src ./src
9
10
CMD ["./mvnw", "spring-boot:run"]
11
COPY .mvn/ .mvn
COPY mvnw pom.xml ./
RUN ./mvnw dependency:go-offline
FROM eclipse-temurin:17-jdk-focal
1
2
WORKDIR /app
3
4
5
6
7
8
COPY src ./src
9
10
CMD ["./mvnw", "spring-boot:run"]
11
COPY src ./src
FROM eclipse-temurin:17-jdk-focal
1
2
WORKDIR /app
3
4
COPY .mvn/ .mvn
5
COPY mvnw pom.xml ./
6
RUN ./mvnw dependency:go-offline
7
8
9
10
CMD ["./mvnw", "spring-boot:run"]
11 CMD ["./mvnw", "spring-boot:run"]
FROM eclipse-temurin:17-jdk-focal
1
2
WORKDIR /app
3
4
COPY .mvn/ .mvn
5
COPY mvnw pom.xml ./
6
RUN ./mvnw dependency:go-offline
7
8
COPY src ./src
9
10
11
10.4
ø Dockerfile
Le Hello World Spring Boot, selon Spring
Boot E
spring.io/guides
# build stage
FROM eclipse-temurin:17-jdk-alpine as build
WORKDIR /workspace/app
COPY mvnw .
COPY .mvn .mvn
COPY pom.xml .
COPY src src
RUN ./mvnw install -DskipTests
RUN mkdir -p target/dependency && (cd target/dependency; jar -xf ../*.jar)
# run stage
FROM eclipse-temurin:17-jdk-alpine
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
11
ø Dockerfile
Le Hello World Spring Boot, selon Spring
Boot E
spring.io/guides
# build stage
FROM eclipse-temurin:17-jdk-alpine as build
WORKDIR /workspace/app
COPY mvnw .
COPY .mvn .mvn
COPY pom.xml .
COPY src src
RUN ./mvnw install -DskipTests
RUN mkdir -p target/dependency && (cd target/dependency; jar -xf ../*.jar)
# run stage
FROM eclipse-temurin:17-jdk-alpine
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# build stage
# run stage
1
FROM eclipse-temurin:17-jdk-alpine as build
2
WORKDIR /workspace/app
3
4
COPY mvnw .
5
COPY .mvn .mvn
6
COPY pom.xml .
7
COPY src src
8
9
RUN ./mvnw install -DskipTests
10
RUN mkdir -p target/dependency && (cd target/dependency; jar -xf ../*.jar)
11
12
13
FROM eclipse-temurin:17-jdk-alpine
14
15
11.1
ø Dockerfile
Le Hello World Spring Boot, selon Spring
Boot E
spring.io/guides
# build stage
FROM eclipse-temurin:17-jdk-alpine as build
WORKDIR /workspace/app
COPY mvnw .
COPY .mvn .mvn
COPY pom.xml .
COPY src src
RUN ./mvnw install -DskipTests
RUN mkdir -p target/dependency && (cd target/dependency; jar -xf ../*.jar)
# run stage
FROM eclipse-temurin:17-jdk-alpine
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# build stage
# run stage
1
FROM eclipse-temurin:17-jdk-alpine as build
2
WORKDIR /workspace/app
3
4
COPY mvnw .
5
COPY .mvn .mvn
6
COPY pom.xml .
7
COPY src src
8
9
RUN ./mvnw install -DskipTests
10
RUN mkdir -p target/dependency && (cd target/dependency; jar -xf ../*.jar)
11
12
13
FROM eclipse-temurin:17-jdk-alpine
14
15
COPY mvnw .
COPY .mvn .mvn
COPY pom.xml .
COPY src src
RUN ./mvnw install -DskipTests
# build stage
1
FROM eclipse-temurin:17-jdk-alpine as build
2
WORKDIR /workspace/app
3
4
5
6
7
8
9
10
RUN mkdir -p target/dependency && (cd target/dependency; jar -xf ../*.jar)
11
12
# run stage
13
FROM eclipse-temurin:17-jdk-alpine
14
15
11.2
ø Dockerfile
Le Hello World Spring Boot, selon Spring
Boot E
spring.io/guides
# build stage
FROM eclipse-temurin:17-jdk-alpine as build
WORKDIR /workspace/app
COPY mvnw .
COPY .mvn .mvn
COPY pom.xml .
COPY src src
RUN ./mvnw install -DskipTests
RUN mkdir -p target/dependency && (cd target/dependency; jar -xf ../*.jar)
# run stage
FROM eclipse-temurin:17-jdk-alpine
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# build stage
# run stage
1
FROM eclipse-temurin:17-jdk-alpine as build
2
WORKDIR /workspace/app
3
4
COPY mvnw .
5
COPY .mvn .mvn
6
COPY pom.xml .
7
COPY src src
8
9
RUN ./mvnw install -DskipTests
10
RUN mkdir -p target/dependency && (cd target/dependency; jar -xf ../*.jar)
11
12
13
FROM eclipse-temurin:17-jdk-alpine
14
15
COPY mvnw .
COPY .mvn .mvn
COPY pom.xml .
COPY src src
RUN ./mvnw install -DskipTests
# build stage
1
FROM eclipse-temurin:17-jdk-alpine as build
2
WORKDIR /workspace/app
3
4
5
6
7
8
9
10
RUN mkdir -p target/dependency && (cd target/dependency; jar -xf ../*.jar)
11
12
# run stage
13
FROM eclipse-temurin:17-jdk-alpine
14
15
RUN mkdir -p target/dependency && (cd target/dependency; jar -xf ../*.jar)
4
COPY mvnw .
5
COPY .mvn .mvn
6
COPY pom.xml .
7
COPY src src
8
9
RUN ./mvnw install -DskipTests
10
11
12
# run stage
13
FROM eclipse-temurin:17-jdk-alpine
14
15
RUN addgroup -S demo && adduser -S demo -G demo
16
USER demo
17
18
11.3
ø Dockerfile
Le Hello World Spring Boot, selon Spring
Boot E
spring.io/guides
# build stage
FROM eclipse-temurin:17-jdk-alpine as build
WORKDIR /workspace/app
COPY mvnw .
COPY .mvn .mvn
COPY pom.xml .
COPY src src
RUN ./mvnw install -DskipTests
RUN mkdir -p target/dependency && (cd target/dependency; jar -xf ../*.jar)
# run stage
FROM eclipse-temurin:17-jdk-alpine
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# build stage
# run stage
1
FROM eclipse-temurin:17-jdk-alpine as build
2
WORKDIR /workspace/app
3
4
COPY mvnw .
5
COPY .mvn .mvn
6
COPY pom.xml .
7
COPY src src
8
9
RUN ./mvnw install -DskipTests
10
RUN mkdir -p target/dependency && (cd target/dependency; jar -xf ../*.jar)
11
12
13
FROM eclipse-temurin:17-jdk-alpine
14
15
COPY mvnw .
COPY .mvn .mvn
COPY pom.xml .
COPY src src
RUN ./mvnw install -DskipTests
# build stage
1
FROM eclipse-temurin:17-jdk-alpine as build
2
WORKDIR /workspace/app
3
4
5
6
7
8
9
10
RUN mkdir -p target/dependency && (cd target/dependency; jar -xf ../*.jar)
11
12
# run stage
13
FROM eclipse-temurin:17-jdk-alpine
14
15
RUN mkdir -p target/dependency && (cd target/dependency; jar -xf ../*.jar)
# build stage
1
FROM eclipse-temurin:17-jdk-alpine as build
2
WORKDIR /workspace/app
3
4
COPY mvnw .
5
COPY .mvn .mvn
6
COPY pom.xml .
7
COPY src src
8
9
RUN ./mvnw install -DskipTests
10
11
12
# run stage
13
FROM eclipse-temurin:17-jdk-alpine
14
15
RUN addgroup -S demo && adduser -S demo -G demo
USER demo
9
RUN ./mvnw install -DskipTests
10
RUN mkdir -p target/dependency && (cd target/dependency; jar -xf ../*.jar)
11
12
# run stage
13
FROM eclipse-temurin:17-jdk-alpine
14
15
16
17
18
VOLUME /tmp
19
ARG DEPENDENCY=/workspace/app/target/dependency
20
COPY --from=build ${DEPENDENCY}/BOOT-INF/lib /app/lib
21
COPY --from=build ${DEPENDENCY}/META-INF /app/META-INF
22
COPY --from=build ${DEPENDENCY}/BOOT-INF/classes /app
23
ENTRYPOINT ["java" " cp" "app:app/ lib/*" "hello Application"]
24
11.4
ø Dockerfile
Le Hello World Spring Boot, selon Spring
Boot E
spring.io/guides
# build stage
FROM eclipse-temurin:17-jdk-alpine as build
WORKDIR /workspace/app
COPY mvnw .
COPY .mvn .mvn
COPY pom.xml .
COPY src src
RUN ./mvnw install -DskipTests
RUN mkdir -p target/dependency && (cd target/dependency; jar -xf ../*.jar)
# run stage
FROM eclipse-temurin:17-jdk-alpine
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# build stage
# run stage
1
FROM eclipse-temurin:17-jdk-alpine as build
2
WORKDIR /workspace/app
3
4
COPY mvnw .
5
COPY .mvn .mvn
6
COPY pom.xml .
7
COPY src src
8
9
RUN ./mvnw install -DskipTests
10
RUN mkdir -p target/dependency && (cd target/dependency; jar -xf ../*.jar)
11
12
13
FROM eclipse-temurin:17-jdk-alpine
14
15
COPY mvnw .
COPY .mvn .mvn
COPY pom.xml .
COPY src src
RUN ./mvnw install -DskipTests
# build stage
1
FROM eclipse-temurin:17-jdk-alpine as build
2
WORKDIR /workspace/app
3
4
5
6
7
8
9
10
RUN mkdir -p target/dependency && (cd target/dependency; jar -xf ../*.jar)
11
12
# run stage
13
FROM eclipse-temurin:17-jdk-alpine
14
15
RUN mkdir -p target/dependency && (cd target/dependency; jar -xf ../*.jar)
# build stage
1
FROM eclipse-temurin:17-jdk-alpine as build
2
WORKDIR /workspace/app
3
4
COPY mvnw .
5
COPY .mvn .mvn
6
COPY pom.xml .
7
COPY src src
8
9
RUN ./mvnw install -DskipTests
10
11
12
# run stage
13
FROM eclipse-temurin:17-jdk-alpine
14
15
# build stage
1
FROM eclipse-temurin:17-jdk-alpine as build
2
WORKDIR /workspace/app
3
4
COPY mvnw .
5
COPY .mvn .mvn
6
COPY pom.xml .
7
COPY src src
8
9
RUN ./mvnw install -DskipTests
10
RUN mkdir -p target/dependency && (cd target/dependency; jar -xf ../*.jar)
11
12
# run stage
13
FROM eclipse-temurin:17-jdk-alpine
14
15
ARG DEPENDENCY=/workspace/app/target/dependency
COPY --from=build ${DEPENDENCY}/BOOT-INF/lib /app/lib
COPY --from=build ${DEPENDENCY}/META-INF /app/META-INF
COPY --from=build ${DEPENDENCY}/BOOT-INF/classes /app
RUN ./mvnw install -DskipTests
10
RUN mkdir -p target/dependency && (cd target/dependency; jar -xf ../*.jar)
11
12
# run stage
13
FROM eclipse-temurin:17-jdk-alpine
14
15
RUN addgroup -S demo && adduser -S demo -G demo
16
USER demo
17
18
VOLUME /tmp
19
20
21
22
23
ENTRYPOINT ["java","-cp","app:app/ lib/*","hello.Application"]
24
11.5
ø Dockerfile
Le Hello World Spring Boot, selon Spring
Boot E
spring.io/guides
# build stage
FROM eclipse-temurin:17-jdk-alpine as build
WORKDIR /workspace/app
COPY mvnw .
COPY .mvn .mvn
COPY pom.xml .
COPY src src
RUN ./mvnw install -DskipTests
RUN mkdir -p target/dependency && (cd target/dependency; jar -xf ../*.jar)
# run stage
FROM eclipse-temurin:17-jdk-alpine
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# build stage
# run stage
1
FROM eclipse-temurin:17-jdk-alpine as build
2
WORKDIR /workspace/app
3
4
COPY mvnw .
5
COPY .mvn .mvn
6
COPY pom.xml .
7
COPY src src
8
9
RUN ./mvnw install -DskipTests
10
RUN mkdir -p target/dependency && (cd target/dependency; jar -xf ../*.jar)
11
12
13
FROM eclipse-temurin:17-jdk-alpine
14
15
COPY mvnw .
COPY .mvn .mvn
COPY pom.xml .
COPY src src
RUN ./mvnw install -DskipTests
# build stage
1
FROM eclipse-temurin:17-jdk-alpine as build
2
WORKDIR /workspace/app
3
4
5
6
7
8
9
10
RUN mkdir -p target/dependency && (cd target/dependency; jar -xf ../*.jar)
11
12
# run stage
13
FROM eclipse-temurin:17-jdk-alpine
14
15
RUN mkdir -p target/dependency && (cd target/dependency; jar -xf ../*.jar)
# build stage
1
FROM eclipse-temurin:17-jdk-alpine as build
2
WORKDIR /workspace/app
3
4
COPY mvnw .
5
COPY .mvn .mvn
6
COPY pom.xml .
7
COPY src src
8
9
RUN ./mvnw install -DskipTests
10
11
12
# run stage
13
FROM eclipse-temurin:17-jdk-alpine
14
15
# build stage
1
FROM eclipse-temurin:17-jdk-alpine as build
2
WORKDIR /workspace/app
3
4
COPY mvnw .
5
COPY .mvn .mvn
6
COPY pom.xml .
7
COPY src src
8
9
RUN ./mvnw install -DskipTests
10
RUN mkdir -p target/dependency && (cd target/dependency; jar -xf ../*.jar)
11
12
# run stage
13
FROM eclipse-temurin:17-jdk-alpine
14
15
# build stage
1
FROM eclipse-temurin:17-jdk-alpine as build
2
WORKDIR /workspace/app
3
4
COPY mvnw .
5
COPY .mvn .mvn
6
COPY pom.xml .
7
COPY src src
8
9
RUN ./mvnw install -DskipTests
10
RUN mkdir -p target/dependency && (cd target/dependency; jar -xf ../*.jar)
11
12
# run stage
13
FROM eclipse-temurin:17-jdk-alpine
14
15
ENTRYPOINT ["java","-cp","app:app/ lib/*","hello.Application"]
RUN ./mvnw install -DskipTests
10
RUN mkdir -p target/dependency && (cd target/dependency; jar -xf ../*.jar)
11
12
# run stage
13
FROM eclipse-temurin:17-jdk-alpine
14
15
RUN addgroup -S demo && adduser -S demo -G demo
16
USER demo
17
18
VOLUME /tmp
19
ARG DEPENDENCY=/workspace/app/target/dependency
20
COPY --from=build ${DEPENDENCY}/BOOT-INF/lib /app/lib
21
COPY --from=build ${DEPENDENCY}/META-INF /app/META-INF
22
COPY --from=build ${DEPENDENCY}/BOOT-INF/classes /app
23
24
11.6
ø Dockerfile
L'instant philosophie
Est-ce que ce Dockerfile était parfait ?
Est-ce qu'on attend d'un·e développeur·euse l'écriture d'un tel
Dockerfile ?
12
Quel est le problème avec les
Dockerfile ?
13
Ce que pense Darren Shepherd
(former @Rancher_Labs, k3s creator)
Darren Shepherd
@ibuildthecloud · Follow
So issues I have
1. Caching. I've been told this is hard. I believe there is
stupider and more effective ways to (not) do it
2. Layers are soooo 2018
3. Multi stage is cool and all, but you really only need two
stages (build env, run env)
4. COPY is kinda pointless.
Darren Shepherd @ibuildthecloud
I don't know if I can shake the urge to try to build a better Dockerfile.
9:25 AM · Jun 27, 2023
43 Reply Copy link
Read 6 replies
Darren Shepherd · Jun 27, 2023
@ibuildthecloud · Follow
Replying to @ibuildthecloud
Layers just suck. They've never really been used effectively and cause
tons of cache issues. I'm not fundamentally opposed to layers, but
maybe just 3. I can do 3.
Darren Shepherd
@ibuildthecloud · Follow
You really can't build a properly good docker image
without multi stage because you don't want your compiler
in the final image. I think a better UX can be built
assuming you basically always want to stages: build and
run.
9:34 AM · Jun 27, 2023
8 Reply Copy link
Read 6 replies
14
Écrire un ø Dockerfile
Image de base, Runtime / Version ( FROM )
Optimiser les layers ( RUN )
Script de démarrage ( ENTRYPOINT )
Configuration ( ENV )
Sécurité
User non-root ( USER )
Versions des packages / runtime à jour
Pas de code source dans l'image finale
Pouvoir patcher les images en cas de nouvelle faille
Pas de secrets
15
Comment font les développeurs qui
doivent écrire un ø Dockerfile ?
_Au pire : Stackoverflow, ChatGPT, ou un tutoriel random
SBof : le Dockerfile de Spring Boot, ou NodeJs
DMieux : ils sont experts Docker, ou un Ops écrit le
Dockerfile avec eux
16
Et c'est pire en entreprise
Chaque projet a son propre Dockerfile , forcément différent
des autres
Bienvenue en enfer m
Quand les normes évoluent, ouvrir des change-request sur
tous les projets de l'entreprise pour mettre à jour les Dockerfile
17
Les images Docker
18
Images ?
øDocker
19
Images ?
øDocker
19.1
Images OCI ?
øDocker
19.2
Images OCI ?
øDocker
19.3
Images OCI ?
øDocker
On parle d'image OCI depuis 2015 (Open Container Initiative)
Normalisé : github.com/opencontainers/image-spec
19.4
La vision qu'on a souvent :
Les layers :
ubuntu:jammy
9dbb3ddf83
eclipse-temurin:17-jdk
2ec73b48ae
mon-appli:1
d1669123f2
distrib + runtime/middleware + code
20
JSON + tar.gz = ‡
On appelle ça un Manifest d'image
{
"schemaVersion": 2,
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"layers": [
{
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
"size": 30430275,
"digest": "sha256:d1669123f28121211977ed38e663dca1a397c0c001e5386598b96c8
},
{
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
"size": 17038759,
"digest": "sha256:2ec73b48ae406646223453ca41d5d6b7cb739853fb7a44f15d35a31
},
{
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
21
✈ manifest.json
JSON + tar.gz = ‡
On appelle ça un Manifest d'image
{
"schemaVersion": 2,
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"layers": [
{
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
"size": 30430275,
"digest": "sha256:d1669123f28121211977ed38e663dca1a397c0c001e5386598b96c8
},
{
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
"size": 17038759,
"digest": "sha256:2ec73b48ae406646223453ca41d5d6b7cb739853fb7a44f15d35a31
},
{
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
"layers": [
{
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
"size": 30430275,
"digest": "sha256:d1669123f28121211977ed38e663dca1a397c0c001e5386598b96c8
},
{
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
"size": 17038759,
"digest": "sha256:2ec73b48ae406646223453ca41d5d6b7cb739853fb7a44f15d35a31
},
{
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
"size": 192587566,
"digest": "sha256:9dbb3ddf83e9096c0e2f32bfa93d16285d2e9586b1a9aa25e33d04c
yp pp j ,
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
21.1
✈ manifest.json
JSON + tar.gz = ‡
On appelle ça un Manifest d'image
{
"schemaVersion": 2,
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"layers": [
{
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
"size": 30430275,
"digest": "sha256:d1669123f28121211977ed38e663dca1a397c0c001e5386598b96c8
},
{
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
"size": 17038759,
"digest": "sha256:2ec73b48ae406646223453ca41d5d6b7cb739853fb7a44f15d35a31
},
{
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
"layers": [
{
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
"size": 30430275,
"digest": "sha256:d1669123f28121211977ed38e663dca1a397c0c001e5386598b96c8
},
{
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
"size": 17038759,
"digest": "sha256:2ec73b48ae406646223453ca41d5d6b7cb739853fb7a44f15d35a31
},
{
{
1
"schemaVersion": 2,
2
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
3
4
5
6
7
8
9
10
11
12
13
14
15
"config": {
"mediaType": "application/vnd.docker.container.image.v1+json",
"size": 6305,
"digest": "sha256:50440189b0f4cd6264c2f03f92acf4772680d864e3a0d422ef4c46373
}
size : 192587566,
17
"digest": "sha256:9dbb3ddf83e9096c0e2f32bfa93d16285d2e9586b1a9aa25e33d04c
18
},
19
{
20
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
21
"size": 175,
22
"digest": "sha256:08d2567dd626029019cc940915699f23b075d05189d99319604fbda
23
}
24
],
25
26
27
28
29
30
}
31
21.2
✈ manifest.json
La configuration aussi fait partie de
l'image OCI !
architecture / OS
variables d'environnements
users
labels
commandes / entrypoints
ports
22
eclipse-temurin:17.0.7_7-jdk
{
"architecture": "amd64",
"config": {
"Hostname": "",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": [
"PATH=/opt/java/openjdk/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr
"JAVA HOME=/opt/java/openjdk",
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
23
Ô config.json
eclipse-temurin:17.0.7_7-jdk
{
"architecture": "amd64",
"config": {
"Hostname": "",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": [
"PATH=/opt/java/openjdk/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr
"JAVA HOME=/opt/java/openjdk",
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
"architecture": "amd64",
{
1
2
"config": {
3
"Hostname": "",
4
"Domainname": "",
5
"User": "",
6
"AttachStdin": false,
7
"AttachStdout": false,
8
"AttachStderr": false,
9
"Tty": false,
10
"OpenStdin": false,
11
"StdinOnce": false,
12
"Env": [
13
"PATH=/opt/java/openjdk/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr
14
"JAVA HOME=/opt/java/openjdk",
15
23.1
Ô config.json
eclipse-temurin:17.0.7_7-jdk
{
"architecture": "amd64",
"config": {
"Hostname": "",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": [
"PATH=/opt/java/openjdk/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr
"JAVA HOME=/opt/java/openjdk",
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
"architecture": "amd64",
{
1
2
"config": {
3
"Hostname": "",
4
"Domainname": "",
5
"User": "",
6
"AttachStdin": false,
7
"AttachStdout": false,
8
"AttachStderr": false,
9
"Tty": false,
10
"OpenStdin": false,
11
"StdinOnce": false,
12
"Env": [
13
"PATH=/opt/java/openjdk/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr
14
"JAVA HOME=/opt/java/openjdk",
15
"Env": [
"PATH=/opt/java/openjdk/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr
"JAVA_HOME=/opt/java/openjdk",
"LANG=en_US.UTF-8",
"LANGUAGE=en_US:en",
"LC_ALL=en_US.UTF-8",
"JAVA_VERSION=jdk-17.0.7+7"
],
AttachStderr : false,
9
"Tty": false,
10
"OpenStdin": false,
11
"StdinOnce": false,
12
13
14
15
16
17
18
19
20
"Cmd": [
21
"jshell"
22
],
23
"Image": "sha256:1dcdc9129900e8da6859de2013f135eb56cc4b67e04ceda95e957b9555
24
23.2
Ô config.json
eclipse-temurin:17.0.7_7-jdk
{
"architecture": "amd64",
"config": {
"Hostname": "",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": [
"PATH=/opt/java/openjdk/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr
"JAVA HOME=/opt/java/openjdk",
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
"architecture": "amd64",
{
1
2
"config": {
3
"Hostname": "",
4
"Domainname": "",
5
"User": "",
6
"AttachStdin": false,
7
"AttachStdout": false,
8
"AttachStderr": false,
9
"Tty": false,
10
"OpenStdin": false,
11
"StdinOnce": false,
12
"Env": [
13
"PATH=/opt/java/openjdk/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr
14
"JAVA HOME=/opt/java/openjdk",
15
"Env": [
"PATH=/opt/java/openjdk/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr
"JAVA HOME=/opt/java/openjdk",
{
1
"architecture": "amd64",
2
"config": {
3
"Hostname": "",
4
"Domainname": "",
5
"User": "",
6
"AttachStdin": false,
7
"AttachStdout": false,
8
"AttachStderr": false,
9
"Tty": false,
10
"OpenStdin": false,
11
"StdinOnce": false,
12
13
14
15
"User": "",
{
1
"architecture": "amd64",
2
"config": {
3
"Hostname": "",
4
"Domainname": "",
5
6
"AttachStdin": false,
7
"AttachStdout": false,
8
"AttachStderr": false,
9
"Tty": false,
10
"OpenStdin": false,
11
"StdinOnce": false,
12
"Env": [
13
"PATH=/opt/java/openjdk/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr
14
"JAVA HOME=/opt/java/openjdk",
15
23.3
Ô config.json
eclipse-temurin:17.0.7_7-jdk
{
"architecture": "amd64",
"config": {
"Hostname": "",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": [
"PATH=/opt/java/openjdk/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr
"JAVA HOME=/opt/java/openjdk",
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
"architecture": "amd64",
{
1
2
"config": {
3
"Hostname": "",
4
"Domainname": "",
5
"User": "",
6
"AttachStdin": false,
7
"AttachStdout": false,
8
"AttachStderr": false,
9
"Tty": false,
10
"OpenStdin": false,
11
"StdinOnce": false,
12
"Env": [
13
"PATH=/opt/java/openjdk/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr
14
"JAVA HOME=/opt/java/openjdk",
15
"Env": [
"PATH=/opt/java/openjdk/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr
"JAVA HOME=/opt/java/openjdk",
{
1
"architecture": "amd64",
2
"config": {
3
"Hostname": "",
4
"Domainname": "",
5
"User": "",
6
"AttachStdin": false,
7
"AttachStdout": false,
8
"AttachStderr": false,
9
"Tty": false,
10
"OpenStdin": false,
11
"StdinOnce": false,
12
13
14
15
"User": "",
{
1
"architecture": "amd64",
2
"config": {
3
"Hostname": "",
4
"Domainname": "",
5
6
"AttachStdin": false,
7
"AttachStdout": false,
8
"AttachStderr": false,
9
"Tty": false,
10
"OpenStdin": false,
11
"StdinOnce": false,
12
"Env": [
13
"PATH=/opt/java/openjdk/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr
14
"JAVA HOME=/opt/java/openjdk",
15
"Labels": {
"org.opencontainers.image.ref.name": "ubuntu",
"org.opencontainers.image.version": "22.04"
}
],
23
"Image": "sha256:1dcdc9129900e8da6859de2013f135eb56cc4b67e04ceda95e957b9555
24
"Volumes": null,
25
"WorkingDir": "",
26
"Entrypoint": null,
27
"OnBuild": null,
28
29
30
31
32
},
33
"created": "2023-06-02T01:44:46.577735785Z",
34
"docker_version": "20.10.23",
35
"os": "linux",
36
"rootfs": {
37
"type": "layers"
38
23.4
Ô config.json
eclipse-temurin:17.0.7_7-jdk
{
"architecture": "amd64",
"config": {
"Hostname": "",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": [
"PATH=/opt/java/openjdk/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr
"JAVA HOME=/opt/java/openjdk",
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
"architecture": "amd64",
{
1
2
"config": {
3
"Hostname": "",
4
"Domainname": "",
5
"User": "",
6
"AttachStdin": false,
7
"AttachStdout": false,
8
"AttachStderr": false,
9
"Tty": false,
10
"OpenStdin": false,
11
"StdinOnce": false,
12
"Env": [
13
"PATH=/opt/java/openjdk/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr
14
"JAVA HOME=/opt/java/openjdk",
15
"Env": [
"PATH=/opt/java/openjdk/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr
"JAVA HOME=/opt/java/openjdk",
{
1
"architecture": "amd64",
2
"config": {
3
"Hostname": "",
4
"Domainname": "",
5
"User": "",
6
"AttachStdin": false,
7
"AttachStdout": false,
8
"AttachStderr": false,
9
"Tty": false,
10
"OpenStdin": false,
11
"StdinOnce": false,
12
13
14
15
"User": "",
{
1
"architecture": "amd64",
2
"config": {
3
"Hostname": "",
4
"Domainname": "",
5
6
"AttachStdin": false,
7
"AttachStdout": false,
8
"AttachStderr": false,
9
"Tty": false,
10
"OpenStdin": false,
11
"StdinOnce": false,
12
"Env": [
13
"PATH=/opt/java/openjdk/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr
14
"JAVA HOME=/opt/java/openjdk",
15
{
1
"architecture": "amd64",
2
"config": {
3
"Hostname": "",
4
"Domainname": "",
5
"User": "",
6
"AttachStdin": false,
7
"AttachStdout": false,
8
"AttachStderr": false,
9
"Tty": false,
10
"OpenStdin": false,
11
"StdinOnce": false,
12
"Env": [
13
"PATH=/opt/java/openjdk/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr
14
"JAVA HOME=/opt/java/openjdk",
15
"Cmd": [
"jshell"
],
"JAVA_HOME=/opt/java/openjdk",
15
"LANG=en_US.UTF-8",
16
"LANGUAGE=en_US:en",
17
"LC_ALL=en_US.UTF-8",
18
"JAVA_VERSION=jdk-17.0.7+7"
19
],
20
21
22
23
"Image": "sha256:1dcdc9129900e8da6859de2013f135eb56cc4b67e04ceda95e957b9555
24
"Volumes": null,
25
"WorkingDir": "",
26
"Entrypoint": null,
27
"OnBuild": null,
28
"Labels": {
29
23.5
Ô config.json
L'instant philosophie
Heureusement qu'ils n'ont pas choisi YAML
24
docker image inspect ú
docker image inspect eclipse-temurin:17.0.7_7-jdk | bat -l json
# on parcours une image avec dive !
dive petclinic:dockerfile
25
> bash
> bash
Une image OCI
Des fichiers tar.gz
Chaque fichier a un digest sha256
De la configuration au format JSON
26
Et si ?
On pouvait générer tout ça ?
On pourrait créer des images OCI, sans avoir besoin de
øDocker ou d'un Dockerfile !
27
L'instant philosophie
ça veut aussi dire, qu'on peut modifier une image, juste en
allant modifier son manifest
28
Les buildpacks
29
30
31
Buildpacks
Concept par Heroku en 2011 pour leur propre besoin de PaaS
multi-langage.
CNB (Cloud Native Buildpacks) initié en 2018, et a rejoint la CNCF
(Cloud Native Computing Foundation) en 2018 en "Incubating".
32
Comment ça fonctionne ?
33
builder
construit une image
buildpack
contribue à une ou plusieurs layers dans la construction
34
Un buildpack est composé de 2
binaires :
/bin/detect : indique si le buildpack doit être activé
/bin/build : contribue à la construction d'une ou plusieurs
layers
35
Le builder contient des scripts
lifecycle :
1. Code source dans un répertoire /workspace
2. Interroge chaque buildpack avec /bin/detect
3. Exécute tous les buildpacks qui doivent être exécutés
4. Chaque buildpack contribue une ou plusieurs layers dans
/layer
5. Les layers dans /layer sont exportées pour créer une
image OCI !
36
37
builder
/cnb
/lifecycle
detector
builder
exporter
37.1
builder
/cnb
/lifecycle
detector
builder
exporter
/buildpacks
/nodejs
bin/detect
bin/build
/java
bin/detect
bin/build
/golang
bin/detect
bin/build
37.2
builder
/workspace
src pom.xml
/cnb
/lifecycle
detector
builder
exporter
/buildpacks
/nodejs
bin/detect
bin/build
/java
bin/detect
bin/build
/golang
bin/detect
bin/build
37.3
builder
/workspace
src pom.xml
/cnb
/lifecycle
detector
/buildpacks
/nodejs
bin/detect
/java
bin/detect
/golang
bin/detect
37.4
builder
/workspace
src pom.xml
/layers
layer-jre
layer-jar
/cnb
/lifecycle
builder
/buildpacks
/java
bin/build
37.5
builder
/layers
layer-jre
layer-jar
/cnb
/lifecycle
exporter
registry
37.6
Mais aussi
Le builder peut charger du cache depuis un registry OCI
( .m2/ , node_modules/ , ...)
Les layers peuvent être reproductibles
Le builder ne s'exécute pas en root
Le builder est une image OCI !
38
Outillage
Le CLI pack permet d'exécuter des builders, pour construire
des images.
# installation du CLI avec apt
sudo add-apt-repository ppa:cncf-buildpacks/pack-cli
sudo apt-get update
sudo apt-get install pack-cli
# premiers secours
pack --help
# construction d'une image OCI !
pack build ma-jolie-image --builder paketobuildpacks/builder:base
39
> bash
> bash
> bash
Les builders de la communauté
Paketo
(Cloud-Foundry / VMWare + Pivotal)
# paketo-base
docker container run --rm -t paketobuildpacks/builder:base ls /cnb/buildpacks
# paketo-tiny construit des image distroless
docker container run --rm -t paketobuildpacks/builder:tiny ls /cnb/buildpacks
40
> bash
> bash
Les builders de la communauté
Heroku
Google
# heroku
docker container run --rm -t heroku/builder:22 ls /cnb/buildpacks
# google
docker container run --rm -t gcr.io/buildpacks/builder:google-22 ls /cnb/buildpacks
41
> bash
> bash
Construction d'image !
# construction d'une image
pack build petclinic:demo --builder paketobuildpacks/builder:base
# parcours des layers construite avec dive
dive petclinic:demo
# inspection de l'image
docker image inspect petclinic:demo | bat -l json
42
> bash
> bash
> bash
L'image produite
ubuntu:bionic
ca-certificates
jdk
SBOM
/app/BOOT-INF/lib
/app/META-INF
/app/BOOT-INF/classes
launcher
metadata
Respecte les bonnes pratiques de
layering de Spring Boot
Est plus légère que celle proposée par
Spring Boot
REPOSITORY TAG IMAGE ID SIZE CREATED
petclinic dockerfile 3c06306a 409MB 7 minute
petclinic demo c3448bd3 315MB 43 years
43
> bash
Une image produite pour une
appli NodeJS
ubuntu:bionic
ca-certificates
node runtime
node_modules
SBOM
/app
launcher
metadata
44
Qui l'utilise en production ? Est-ce que
c'est mature ?
45
Qui l'utilise en production ? Est-ce que
c'est mature ?
Google App
Engine
45.1
Qui l'utilise en production ? Est-ce que
c'est mature ?
Google App
Engine
Google Cloud
Run
45.2
Qui l'utilise en production ? Est-ce que
c'est mature ?
Google App
Engine
Google Cloud
Run
Google Cloud
Functions
45.3
Qui l'utilise en production ? Est-ce que
c'est mature ?
Google App
Engine
Google Cloud
Run
Google Cloud
Functions
Azure Container
Apps
45.4
Qui l'utilise en production ? Est-ce que
c'est mature ?
Google App
Engine
Google Cloud
Run
Google Cloud
Functions
Azure Container
Apps
Gitlab Auto
DevOps
45.5
Qui l'utilise en production ? Est-ce que
c'est mature ?
Google App
Engine
Google Cloud
Run
Google Cloud
Functions
Azure Container
Apps
Gitlab Auto
DevOps
KNative
45.6
Qui l'utilise en production ? Est-ce que
c'est mature ?
Google App
Engine
Google Cloud
Run
Google Cloud
Functions
Azure Container
Apps
Gitlab Auto
DevOps
KNative
Dokku
45.7
Qui l'utilise en production ? Est-ce que
c'est mature ?
Google App
Engine
Google Cloud
Run
Google Cloud
Functions
Azure Container
Apps
Gitlab Auto
DevOps
KNative
Dokku Spring Boot
(mvn spring-
45.8
Qui l'utilise en production ? Est-ce que
c'est mature ?
Google App
Engine
Google Cloud
Run
Google Cloud
Functions
Azure Container
Apps
Gitlab Auto
DevOps
KNative
Dokku Spring Boot
(mvn spring-
Riff (Netlify)
45.9
Quels avantages ?
46
En vrac
Plus besoin de maintenir un Dockerfile
Gestion de cache, réutilisation de layers existantes
Modularité
47
SBoM
Software Bill of Materials
Chaque buildpack contribue à la construction d'un SBoM dans
une layer dédiée
C'est vos RSSI et vos RSO qui vont être contents y
48
Reproductibilité des builds ? E
À partir du même code source, produit strictement le même
binaire / la même image, avec le même digest sha256 !
Nécessite de mettre à "0" les dates des fichiers.
Ça évite de produire de "nouvelles" layers si du code n'a pas
changé (exemple, les libs)
"Created": "1980-01-01T00:00:01Z"
REPOSITORY TAG IMAGE ID CREATED SIZE
petclinic demo c3448bd3501d 43 years ago 315MB
49
{} JSON
> bash
Reproductibilité des builds ? E
# pull d'une image construite précédemment
docker image pull rg.fr-par.scw.cloud/sunny-tech-buildpacks/petclinic:paketo-base
# comparaison des layers
docker image inspect petclinic:demo | jq '.[].RootFS'
docker image inspect rg.fr-par.scw.cloud/sunny-tech-buildpacks/petclinic:paketo-bas
diff -s <(docker image inspect petclinic:demo | jq '.[].RootFS') <(docker image ins
50
> bash
> bash
Reproductibilité des builds ? `
Les images buildées sur une CI et sur le poste développeur ont
la même signature !
Les images buildées par deux pipelines de CI consécutifs sont
identiques !
51
Le rebase d'image
Oui, ça veut bien dire ce que vous imaginez !
ubuntu:jammy
9dbb3ddf83
eclipse-temurin:17-jdk
2ec73b48ae
mon appli
d1669123f2
eclipse-temurin:20-jdk
40915699f2
mon appli
d1669123f2
ubuntu:jammy
9dbb3ddf83
52
Le rebase d'image
pack rebase petclinic:demo --run-image <new-base-image>
53
> bash
Le rebase d'image
Se fait au niveau du ✈Manifest
Implémenté par la plupart des builders sur la couche
"distribution"
Permet de modifier les layers basses d'une image, sans avoir
besoin de la reconstruire
Permet de patcher rapidement une image, sans rebuild
54
Créer son propre builder 
Choisir son image de base
Réutiliser des buildpacks existants
Implémenter les langages manquants
55
Take-aways
56
Les buildpacks c'est cool „
Un builder pour supporter tous vos langages
Génère des SBOM pour votre RSSI/RSO préféré
Gestion du cache intégrée
Facile d'utilisation
Implémente les bonnes pratiques de layering, sécurité
Reproductibilité des builds `
Rebase d'images `
57
Mais... ›
Créer son propre builder, c'est compliqué
Le CLI pack utilise Docker, ou Podman
Mais y'a moyen d'exécuter un builder sans Docker :
kpack
tekton
Customisation pas forcément évidente
58
Merci pour votre attention !
Un petit feedback ? =>
Julien Wittouck - @CodeKaio
59
Laissez tomber vos Dockerfile, adoptez un Buildpack !

Contenu connexe

Tendances

「Docker +VLAN 環境」アプリケーション実行環境の構築
「Docker +VLAN 環境」アプリケーション実行環境の構築「Docker +VLAN 環境」アプリケーション実行環境の構築
「Docker +VLAN 環境」アプリケーション実行環境の構築Fuva Brain
 
BuildKitの概要と最近の機能
BuildKitの概要と最近の機能BuildKitの概要と最近の機能
BuildKitの概要と最近の機能Kohei Tokunaga
 
KFServing - Serverless Model Inferencing
KFServing - Serverless Model InferencingKFServing - Serverless Model Inferencing
KFServing - Serverless Model InferencingAnimesh Singh
 
PowerShellでWebブラウザ(Selenium Webdriver)を動かした話
PowerShellでWebブラウザ(Selenium Webdriver)を動かした話PowerShellでWebブラウザ(Selenium Webdriver)を動かした話
PowerShellでWebブラウザ(Selenium Webdriver)を動かした話洋史 東平
 
[KubeConUS2019 Docker, Inc. Booth] Distributed Builds on Kubernetes with Bui...
 [KubeConUS2019 Docker, Inc. Booth] Distributed Builds on Kubernetes with Bui... [KubeConUS2019 Docker, Inc. Booth] Distributed Builds on Kubernetes with Bui...
[KubeConUS2019 Docker, Inc. Booth] Distributed Builds on Kubernetes with Bui...Akihiro Suda
 
[오픈소스컨설팅]Subversion vs git - 참을 수 없는 간단함
[오픈소스컨설팅]Subversion vs git - 참을 수 없는 간단함[오픈소스컨설팅]Subversion vs git - 참을 수 없는 간단함
[오픈소스컨설팅]Subversion vs git - 참을 수 없는 간단함Ji-Woong Choi
 
ソフトウェア構成管理入門
ソフトウェア構成管理入門ソフトウェア構成管理入門
ソフトウェア構成管理入門智治 長沢
 
YAML Tips For Kubernetes by Neependra Khare
YAML Tips For Kubernetes by Neependra KhareYAML Tips For Kubernetes by Neependra Khare
YAML Tips For Kubernetes by Neependra KhareCodeOps Technologies LLP
 
Kubernetes Helm: Why It Matters
Kubernetes Helm: Why It MattersKubernetes Helm: Why It Matters
Kubernetes Helm: Why It MattersPlatform9
 
Quality in a Square. K8s-native Quality Assurance of Microservices with Testkube
Quality in a Square. K8s-native Quality Assurance of Microservices with TestkubeQuality in a Square. K8s-native Quality Assurance of Microservices with Testkube
Quality in a Square. K8s-native Quality Assurance of Microservices with TestkubeQAware GmbH
 
docker installation and basics
docker installation and basicsdocker installation and basics
docker installation and basicsWalid Ashraf
 
DCSF19 Dockerfile Best Practices
DCSF19 Dockerfile Best PracticesDCSF19 Dockerfile Best Practices
DCSF19 Dockerfile Best PracticesDocker, Inc.
 
.NET Day - Continuous Deployment Showdown: Traditional CI/CD vs. GitOps
.NET Day - Continuous Deployment Showdown: Traditional CI/CD vs. GitOps.NET Day - Continuous Deployment Showdown: Traditional CI/CD vs. GitOps
.NET Day - Continuous Deployment Showdown: Traditional CI/CD vs. GitOpsMarc Müller
 
サーバ構築を自動化する 〜Ansible〜
サーバ構築を自動化する 〜Ansible〜サーバ構築を自動化する 〜Ansible〜
サーバ構築を自動化する 〜Ansible〜Yui Ito
 

Tendances (20)

「Docker +VLAN 環境」アプリケーション実行環境の構築
「Docker +VLAN 環境」アプリケーション実行環境の構築「Docker +VLAN 環境」アプリケーション実行環境の構築
「Docker +VLAN 環境」アプリケーション実行環境の構築
 
New VIdeo CODEC AV1
New VIdeo CODEC AV1 New VIdeo CODEC AV1
New VIdeo CODEC AV1
 
BuildKitの概要と最近の機能
BuildKitの概要と最近の機能BuildKitの概要と最近の機能
BuildKitの概要と最近の機能
 
KFServing - Serverless Model Inferencing
KFServing - Serverless Model InferencingKFServing - Serverless Model Inferencing
KFServing - Serverless Model Inferencing
 
PowerShellでWebブラウザ(Selenium Webdriver)を動かした話
PowerShellでWebブラウザ(Selenium Webdriver)を動かした話PowerShellでWebブラウザ(Selenium Webdriver)を動かした話
PowerShellでWebブラウザ(Selenium Webdriver)を動かした話
 
Klocworkのご紹介
Klocworkのご紹介Klocworkのご紹介
Klocworkのご紹介
 
Docker.pptx
Docker.pptxDocker.pptx
Docker.pptx
 
[KubeConUS2019 Docker, Inc. Booth] Distributed Builds on Kubernetes with Bui...
 [KubeConUS2019 Docker, Inc. Booth] Distributed Builds on Kubernetes with Bui... [KubeConUS2019 Docker, Inc. Booth] Distributed Builds on Kubernetes with Bui...
[KubeConUS2019 Docker, Inc. Booth] Distributed Builds on Kubernetes with Bui...
 
[오픈소스컨설팅]Subversion vs git - 참을 수 없는 간단함
[오픈소스컨설팅]Subversion vs git - 참을 수 없는 간단함[오픈소스컨설팅]Subversion vs git - 참을 수 없는 간단함
[오픈소스컨설팅]Subversion vs git - 참을 수 없는 간단함
 
CI-CD WITH GITLAB WORKFLOW
CI-CD WITH GITLAB WORKFLOWCI-CD WITH GITLAB WORKFLOW
CI-CD WITH GITLAB WORKFLOW
 
ソフトウェア構成管理入門
ソフトウェア構成管理入門ソフトウェア構成管理入門
ソフトウェア構成管理入門
 
YAML Tips For Kubernetes by Neependra Khare
YAML Tips For Kubernetes by Neependra KhareYAML Tips For Kubernetes by Neependra Khare
YAML Tips For Kubernetes by Neependra Khare
 
Kubernetes Helm: Why It Matters
Kubernetes Helm: Why It MattersKubernetes Helm: Why It Matters
Kubernetes Helm: Why It Matters
 
Quality in a Square. K8s-native Quality Assurance of Microservices with Testkube
Quality in a Square. K8s-native Quality Assurance of Microservices with TestkubeQuality in a Square. K8s-native Quality Assurance of Microservices with Testkube
Quality in a Square. K8s-native Quality Assurance of Microservices with Testkube
 
docker installation and basics
docker installation and basicsdocker installation and basics
docker installation and basics
 
DevOps 3 - Docker.pdf
DevOps 3 - Docker.pdfDevOps 3 - Docker.pdf
DevOps 3 - Docker.pdf
 
DCSF19 Dockerfile Best Practices
DCSF19 Dockerfile Best PracticesDCSF19 Dockerfile Best Practices
DCSF19 Dockerfile Best Practices
 
.NET Day - Continuous Deployment Showdown: Traditional CI/CD vs. GitOps
.NET Day - Continuous Deployment Showdown: Traditional CI/CD vs. GitOps.NET Day - Continuous Deployment Showdown: Traditional CI/CD vs. GitOps
.NET Day - Continuous Deployment Showdown: Traditional CI/CD vs. GitOps
 
Docker Basics
Docker BasicsDocker Basics
Docker Basics
 
サーバ構築を自動化する 〜Ansible〜
サーバ構築を自動化する 〜Ansible〜サーバ構築を自動化する 〜Ansible〜
サーバ構築を自動化する 〜Ansible〜
 

Similaire à Laissez tomber vos Dockerfile, adoptez un Buildpack !

Spring Boot & Containers - Do's & Don'ts
Spring Boot & Containers - Do's & Don'tsSpring Boot & Containers - Do's & Don'ts
Spring Boot & Containers - Do's & Don'tsJulien Wittouck
 
Sauvegarder et restaurer l'état des applications mobiles
Sauvegarder et restaurer l'état des applications mobilesSauvegarder et restaurer l'état des applications mobiles
Sauvegarder et restaurer l'état des applications mobilespprem
 
Oxalide Workshop #4 - Docker, des tours dans le petit bassin
Oxalide Workshop #4 - Docker, des tours dans le petit bassinOxalide Workshop #4 - Docker, des tours dans le petit bassin
Oxalide Workshop #4 - Docker, des tours dans le petit bassinLudovic Piot
 
Oxalide Workshop #4 - Docker, des tours dans le petit bassin
Oxalide Workshop #4 - Docker, des tours dans le petit bassinOxalide Workshop #4 - Docker, des tours dans le petit bassin
Oxalide Workshop #4 - Docker, des tours dans le petit bassinOxalide
 
Apache flink - prise en main rapide
Apache flink - prise en main rapideApache flink - prise en main rapide
Apache flink - prise en main rapideBilal Baltagi
 
Environnement java
Environnement javaEnvironnement java
Environnement javaInes Ouaz
 
Docker, ça mange quoi au printemps
Docker, ça mange quoi au printempsDocker, ça mange quoi au printemps
Docker, ça mange quoi au printempsJulien Maitrehenry
 
Julien Maitrehenry - Docker, ça mange quoi au printemps
Julien Maitrehenry - Docker, ça mange quoi au printempsJulien Maitrehenry - Docker, ça mange quoi au printemps
Julien Maitrehenry - Docker, ça mange quoi au printempsWeb à Québec
 
CI, CD, pipelines, conteneurs : la cohabitation est elle possible ?
CI, CD, pipelines, conteneurs : la cohabitation est elle possible ?CI, CD, pipelines, conteneurs : la cohabitation est elle possible ?
CI, CD, pipelines, conteneurs : la cohabitation est elle possible ?Membré Guillaume
 
20120110 paris jug-packaging-natif
20120110 paris jug-packaging-natif20120110 paris jug-packaging-natif
20120110 paris jug-packaging-natifHenri Gomez
 
5390997 Support formation : Construire et administrer vos conteneurs avec Doc...
5390997 Support formation : Construire et administrer vos conteneurs avec Doc...5390997 Support formation : Construire et administrer vos conteneurs avec Doc...
5390997 Support formation : Construire et administrer vos conteneurs avec Doc...AbdellahELMAMOUN
 
JCertif 2012 : Maven par la pratique
JCertif 2012 : Maven par la pratiqueJCertif 2012 : Maven par la pratique
JCertif 2012 : Maven par la pratiqueRossi Oddet
 
Tutorial android - créer des apps
Tutorial android - créer des appsTutorial android - créer des apps
Tutorial android - créer des appsNoé Breiss
 
Grunt / Bower / Yeoman ou comment automatiser le développement d’un projet we...
Grunt / Bower / Yeoman ou comment automatiser le développement d’un projet we...Grunt / Bower / Yeoman ou comment automatiser le développement d’un projet we...
Grunt / Bower / Yeoman ou comment automatiser le développement d’un projet we...Microsoft
 

Similaire à Laissez tomber vos Dockerfile, adoptez un Buildpack ! (20)

Jenkins Workflow
Jenkins WorkflowJenkins Workflow
Jenkins Workflow
 
Spring Boot & Containers - Do's & Don'ts
Spring Boot & Containers - Do's & Don'tsSpring Boot & Containers - Do's & Don'ts
Spring Boot & Containers - Do's & Don'ts
 
Sauvegarder et restaurer l'état des applications mobiles
Sauvegarder et restaurer l'état des applications mobilesSauvegarder et restaurer l'état des applications mobiles
Sauvegarder et restaurer l'état des applications mobiles
 
Oxalide Workshop #4 - Docker, des tours dans le petit bassin
Oxalide Workshop #4 - Docker, des tours dans le petit bassinOxalide Workshop #4 - Docker, des tours dans le petit bassin
Oxalide Workshop #4 - Docker, des tours dans le petit bassin
 
Oxalide Workshop #4 - Docker, des tours dans le petit bassin
Oxalide Workshop #4 - Docker, des tours dans le petit bassinOxalide Workshop #4 - Docker, des tours dans le petit bassin
Oxalide Workshop #4 - Docker, des tours dans le petit bassin
 
Cours cordova & REST
Cours cordova & RESTCours cordova & REST
Cours cordova & REST
 
Installation nconf
Installation nconfInstallation nconf
Installation nconf
 
Apache flink - prise en main rapide
Apache flink - prise en main rapideApache flink - prise en main rapide
Apache flink - prise en main rapide
 
Environnement java
Environnement javaEnvironnement java
Environnement java
 
Code, ship and run
Code, ship and runCode, ship and run
Code, ship and run
 
Docker, ça mange quoi au printemps
Docker, ça mange quoi au printempsDocker, ça mange quoi au printemps
Docker, ça mange quoi au printemps
 
Julien Maitrehenry - Docker, ça mange quoi au printemps
Julien Maitrehenry - Docker, ça mange quoi au printempsJulien Maitrehenry - Docker, ça mange quoi au printemps
Julien Maitrehenry - Docker, ça mange quoi au printemps
 
CI, CD, pipelines, conteneurs : la cohabitation est elle possible ?
CI, CD, pipelines, conteneurs : la cohabitation est elle possible ?CI, CD, pipelines, conteneurs : la cohabitation est elle possible ?
CI, CD, pipelines, conteneurs : la cohabitation est elle possible ?
 
Apache Cordova 3.3 de zéro
Apache Cordova 3.3 de zéroApache Cordova 3.3 de zéro
Apache Cordova 3.3 de zéro
 
20120110 paris jug-packaging-natif
20120110 paris jug-packaging-natif20120110 paris jug-packaging-natif
20120110 paris jug-packaging-natif
 
5390997 Support formation : Construire et administrer vos conteneurs avec Doc...
5390997 Support formation : Construire et administrer vos conteneurs avec Doc...5390997 Support formation : Construire et administrer vos conteneurs avec Doc...
5390997 Support formation : Construire et administrer vos conteneurs avec Doc...
 
JCertif 2012 : Maven par la pratique
JCertif 2012 : Maven par la pratiqueJCertif 2012 : Maven par la pratique
JCertif 2012 : Maven par la pratique
 
Tutorial android - créer des apps
Tutorial android - créer des appsTutorial android - créer des apps
Tutorial android - créer des apps
 
Tutorial android
Tutorial androidTutorial android
Tutorial android
 
Grunt / Bower / Yeoman ou comment automatiser le développement d’un projet we...
Grunt / Bower / Yeoman ou comment automatiser le développement d’un projet we...Grunt / Bower / Yeoman ou comment automatiser le développement d’un projet we...
Grunt / Bower / Yeoman ou comment automatiser le développement d’un projet we...
 

Laissez tomber vos Dockerfile, adoptez un Buildpack !

  • 1. Laissez tomber vos Dockerfile, adoptez un Buildpack ! Julien Wittouck - @CodeKaio 1
  • 2. Vous êtes au bon endroit si Vous êtes un·e Dev Vous être un·e Ops Vous faites souvent joujou avec Docker ! 2
  • 3. Exécuter une application dans un container, c'est facile. Un Dockerfile øet hop Æ, en prod ! 3
  • 5. J'écris des (mauvais _) Dockerfile depuis 2015 FROM node:latest COPY . . RUN npm install CMD ["npm", "start"] 1 2 3 4 FROM openjdk:latest COPY . . CMD ["./mvnw", "spring-boot:run"] 1 2 3 5 ø Dockerfile ø Dockerfile
  • 6. Salut 9 Moi c’est Julien Freelance @CodeKaio Associé @Ekité Teacher @univ-lille dSpeaker (DevFest Lille - Sunny Tech) ûReviewer Cloud Nord 6
  • 9. Comment Docker construit une image ? "Exécute" le Dockerfile Dans des containers séparés "SNAPSHOT" le filesystem à chaque étape pour créer les layers 9
  • 10. Le Hello World Spring Boot, selon Docker _ www.docker.com/blog FROM eclipse-temurin:17-jdk-focal WORKDIR /app COPY .mvn/ .mvn COPY mvnw pom.xml ./ RUN ./mvnw dependency:go-offline COPY src ./src CMD ["./mvnw", "spring-boot:run"] 1 2 3 4 5 6 7 8 9 10 11 10 ø Dockerfile
  • 11. Le Hello World Spring Boot, selon Docker _ www.docker.com/blog FROM eclipse-temurin:17-jdk-focal WORKDIR /app COPY .mvn/ .mvn COPY mvnw pom.xml ./ RUN ./mvnw dependency:go-offline COPY src ./src CMD ["./mvnw", "spring-boot:run"] 1 2 3 4 5 6 7 8 9 10 11 FROM eclipse-temurin:17-jdk-focal 1 2 WORKDIR /app 3 4 COPY .mvn/ .mvn 5 COPY mvnw pom.xml ./ 6 RUN ./mvnw dependency:go-offline 7 8 COPY src ./src 9 10 CMD ["./mvnw", "spring-boot:run"] 11 10.1 ø Dockerfile
  • 12. Le Hello World Spring Boot, selon Docker _ www.docker.com/blog FROM eclipse-temurin:17-jdk-focal WORKDIR /app COPY .mvn/ .mvn COPY mvnw pom.xml ./ RUN ./mvnw dependency:go-offline COPY src ./src CMD ["./mvnw", "spring-boot:run"] 1 2 3 4 5 6 7 8 9 10 11 FROM eclipse-temurin:17-jdk-focal 1 2 WORKDIR /app 3 4 COPY .mvn/ .mvn 5 COPY mvnw pom.xml ./ 6 RUN ./mvnw dependency:go-offline 7 8 COPY src ./src 9 10 CMD ["./mvnw", "spring-boot:run"] 11 COPY .mvn/ .mvn COPY mvnw pom.xml ./ RUN ./mvnw dependency:go-offline FROM eclipse-temurin:17-jdk-focal 1 2 WORKDIR /app 3 4 5 6 7 8 COPY src ./src 9 10 CMD ["./mvnw", "spring-boot:run"] 11 10.2 ø Dockerfile
  • 13. Le Hello World Spring Boot, selon Docker _ www.docker.com/blog FROM eclipse-temurin:17-jdk-focal WORKDIR /app COPY .mvn/ .mvn COPY mvnw pom.xml ./ RUN ./mvnw dependency:go-offline COPY src ./src CMD ["./mvnw", "spring-boot:run"] 1 2 3 4 5 6 7 8 9 10 11 FROM eclipse-temurin:17-jdk-focal 1 2 WORKDIR /app 3 4 COPY .mvn/ .mvn 5 COPY mvnw pom.xml ./ 6 RUN ./mvnw dependency:go-offline 7 8 COPY src ./src 9 10 CMD ["./mvnw", "spring-boot:run"] 11 COPY .mvn/ .mvn COPY mvnw pom.xml ./ RUN ./mvnw dependency:go-offline FROM eclipse-temurin:17-jdk-focal 1 2 WORKDIR /app 3 4 5 6 7 8 COPY src ./src 9 10 CMD ["./mvnw", "spring-boot:run"] 11 COPY src ./src FROM eclipse-temurin:17-jdk-focal 1 2 WORKDIR /app 3 4 COPY .mvn/ .mvn 5 COPY mvnw pom.xml ./ 6 RUN ./mvnw dependency:go-offline 7 8 9 10 CMD ["./mvnw", "spring-boot:run"] 11 10.3 ø Dockerfile
  • 14. Le Hello World Spring Boot, selon Docker _ www.docker.com/blog FROM eclipse-temurin:17-jdk-focal WORKDIR /app COPY .mvn/ .mvn COPY mvnw pom.xml ./ RUN ./mvnw dependency:go-offline COPY src ./src CMD ["./mvnw", "spring-boot:run"] 1 2 3 4 5 6 7 8 9 10 11 FROM eclipse-temurin:17-jdk-focal 1 2 WORKDIR /app 3 4 COPY .mvn/ .mvn 5 COPY mvnw pom.xml ./ 6 RUN ./mvnw dependency:go-offline 7 8 COPY src ./src 9 10 CMD ["./mvnw", "spring-boot:run"] 11 COPY .mvn/ .mvn COPY mvnw pom.xml ./ RUN ./mvnw dependency:go-offline FROM eclipse-temurin:17-jdk-focal 1 2 WORKDIR /app 3 4 5 6 7 8 COPY src ./src 9 10 CMD ["./mvnw", "spring-boot:run"] 11 COPY src ./src FROM eclipse-temurin:17-jdk-focal 1 2 WORKDIR /app 3 4 COPY .mvn/ .mvn 5 COPY mvnw pom.xml ./ 6 RUN ./mvnw dependency:go-offline 7 8 9 10 CMD ["./mvnw", "spring-boot:run"] 11 CMD ["./mvnw", "spring-boot:run"] FROM eclipse-temurin:17-jdk-focal 1 2 WORKDIR /app 3 4 COPY .mvn/ .mvn 5 COPY mvnw pom.xml ./ 6 RUN ./mvnw dependency:go-offline 7 8 COPY src ./src 9 10 11 10.4 ø Dockerfile
  • 15. Le Hello World Spring Boot, selon Spring Boot E spring.io/guides # build stage FROM eclipse-temurin:17-jdk-alpine as build WORKDIR /workspace/app COPY mvnw . COPY .mvn .mvn COPY pom.xml . COPY src src RUN ./mvnw install -DskipTests RUN mkdir -p target/dependency && (cd target/dependency; jar -xf ../*.jar) # run stage FROM eclipse-temurin:17-jdk-alpine 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 11 ø Dockerfile
  • 16. Le Hello World Spring Boot, selon Spring Boot E spring.io/guides # build stage FROM eclipse-temurin:17-jdk-alpine as build WORKDIR /workspace/app COPY mvnw . COPY .mvn .mvn COPY pom.xml . COPY src src RUN ./mvnw install -DskipTests RUN mkdir -p target/dependency && (cd target/dependency; jar -xf ../*.jar) # run stage FROM eclipse-temurin:17-jdk-alpine 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 # build stage # run stage 1 FROM eclipse-temurin:17-jdk-alpine as build 2 WORKDIR /workspace/app 3 4 COPY mvnw . 5 COPY .mvn .mvn 6 COPY pom.xml . 7 COPY src src 8 9 RUN ./mvnw install -DskipTests 10 RUN mkdir -p target/dependency && (cd target/dependency; jar -xf ../*.jar) 11 12 13 FROM eclipse-temurin:17-jdk-alpine 14 15 11.1 ø Dockerfile
  • 17. Le Hello World Spring Boot, selon Spring Boot E spring.io/guides # build stage FROM eclipse-temurin:17-jdk-alpine as build WORKDIR /workspace/app COPY mvnw . COPY .mvn .mvn COPY pom.xml . COPY src src RUN ./mvnw install -DskipTests RUN mkdir -p target/dependency && (cd target/dependency; jar -xf ../*.jar) # run stage FROM eclipse-temurin:17-jdk-alpine 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 # build stage # run stage 1 FROM eclipse-temurin:17-jdk-alpine as build 2 WORKDIR /workspace/app 3 4 COPY mvnw . 5 COPY .mvn .mvn 6 COPY pom.xml . 7 COPY src src 8 9 RUN ./mvnw install -DskipTests 10 RUN mkdir -p target/dependency && (cd target/dependency; jar -xf ../*.jar) 11 12 13 FROM eclipse-temurin:17-jdk-alpine 14 15 COPY mvnw . COPY .mvn .mvn COPY pom.xml . COPY src src RUN ./mvnw install -DskipTests # build stage 1 FROM eclipse-temurin:17-jdk-alpine as build 2 WORKDIR /workspace/app 3 4 5 6 7 8 9 10 RUN mkdir -p target/dependency && (cd target/dependency; jar -xf ../*.jar) 11 12 # run stage 13 FROM eclipse-temurin:17-jdk-alpine 14 15 11.2 ø Dockerfile
  • 18. Le Hello World Spring Boot, selon Spring Boot E spring.io/guides # build stage FROM eclipse-temurin:17-jdk-alpine as build WORKDIR /workspace/app COPY mvnw . COPY .mvn .mvn COPY pom.xml . COPY src src RUN ./mvnw install -DskipTests RUN mkdir -p target/dependency && (cd target/dependency; jar -xf ../*.jar) # run stage FROM eclipse-temurin:17-jdk-alpine 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 # build stage # run stage 1 FROM eclipse-temurin:17-jdk-alpine as build 2 WORKDIR /workspace/app 3 4 COPY mvnw . 5 COPY .mvn .mvn 6 COPY pom.xml . 7 COPY src src 8 9 RUN ./mvnw install -DskipTests 10 RUN mkdir -p target/dependency && (cd target/dependency; jar -xf ../*.jar) 11 12 13 FROM eclipse-temurin:17-jdk-alpine 14 15 COPY mvnw . COPY .mvn .mvn COPY pom.xml . COPY src src RUN ./mvnw install -DskipTests # build stage 1 FROM eclipse-temurin:17-jdk-alpine as build 2 WORKDIR /workspace/app 3 4 5 6 7 8 9 10 RUN mkdir -p target/dependency && (cd target/dependency; jar -xf ../*.jar) 11 12 # run stage 13 FROM eclipse-temurin:17-jdk-alpine 14 15 RUN mkdir -p target/dependency && (cd target/dependency; jar -xf ../*.jar) 4 COPY mvnw . 5 COPY .mvn .mvn 6 COPY pom.xml . 7 COPY src src 8 9 RUN ./mvnw install -DskipTests 10 11 12 # run stage 13 FROM eclipse-temurin:17-jdk-alpine 14 15 RUN addgroup -S demo && adduser -S demo -G demo 16 USER demo 17 18 11.3 ø Dockerfile
  • 19. Le Hello World Spring Boot, selon Spring Boot E spring.io/guides # build stage FROM eclipse-temurin:17-jdk-alpine as build WORKDIR /workspace/app COPY mvnw . COPY .mvn .mvn COPY pom.xml . COPY src src RUN ./mvnw install -DskipTests RUN mkdir -p target/dependency && (cd target/dependency; jar -xf ../*.jar) # run stage FROM eclipse-temurin:17-jdk-alpine 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 # build stage # run stage 1 FROM eclipse-temurin:17-jdk-alpine as build 2 WORKDIR /workspace/app 3 4 COPY mvnw . 5 COPY .mvn .mvn 6 COPY pom.xml . 7 COPY src src 8 9 RUN ./mvnw install -DskipTests 10 RUN mkdir -p target/dependency && (cd target/dependency; jar -xf ../*.jar) 11 12 13 FROM eclipse-temurin:17-jdk-alpine 14 15 COPY mvnw . COPY .mvn .mvn COPY pom.xml . COPY src src RUN ./mvnw install -DskipTests # build stage 1 FROM eclipse-temurin:17-jdk-alpine as build 2 WORKDIR /workspace/app 3 4 5 6 7 8 9 10 RUN mkdir -p target/dependency && (cd target/dependency; jar -xf ../*.jar) 11 12 # run stage 13 FROM eclipse-temurin:17-jdk-alpine 14 15 RUN mkdir -p target/dependency && (cd target/dependency; jar -xf ../*.jar) # build stage 1 FROM eclipse-temurin:17-jdk-alpine as build 2 WORKDIR /workspace/app 3 4 COPY mvnw . 5 COPY .mvn .mvn 6 COPY pom.xml . 7 COPY src src 8 9 RUN ./mvnw install -DskipTests 10 11 12 # run stage 13 FROM eclipse-temurin:17-jdk-alpine 14 15 RUN addgroup -S demo && adduser -S demo -G demo USER demo 9 RUN ./mvnw install -DskipTests 10 RUN mkdir -p target/dependency && (cd target/dependency; jar -xf ../*.jar) 11 12 # run stage 13 FROM eclipse-temurin:17-jdk-alpine 14 15 16 17 18 VOLUME /tmp 19 ARG DEPENDENCY=/workspace/app/target/dependency 20 COPY --from=build ${DEPENDENCY}/BOOT-INF/lib /app/lib 21 COPY --from=build ${DEPENDENCY}/META-INF /app/META-INF 22 COPY --from=build ${DEPENDENCY}/BOOT-INF/classes /app 23 ENTRYPOINT ["java" " cp" "app:app/ lib/*" "hello Application"] 24 11.4 ø Dockerfile
  • 20. Le Hello World Spring Boot, selon Spring Boot E spring.io/guides # build stage FROM eclipse-temurin:17-jdk-alpine as build WORKDIR /workspace/app COPY mvnw . COPY .mvn .mvn COPY pom.xml . COPY src src RUN ./mvnw install -DskipTests RUN mkdir -p target/dependency && (cd target/dependency; jar -xf ../*.jar) # run stage FROM eclipse-temurin:17-jdk-alpine 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 # build stage # run stage 1 FROM eclipse-temurin:17-jdk-alpine as build 2 WORKDIR /workspace/app 3 4 COPY mvnw . 5 COPY .mvn .mvn 6 COPY pom.xml . 7 COPY src src 8 9 RUN ./mvnw install -DskipTests 10 RUN mkdir -p target/dependency && (cd target/dependency; jar -xf ../*.jar) 11 12 13 FROM eclipse-temurin:17-jdk-alpine 14 15 COPY mvnw . COPY .mvn .mvn COPY pom.xml . COPY src src RUN ./mvnw install -DskipTests # build stage 1 FROM eclipse-temurin:17-jdk-alpine as build 2 WORKDIR /workspace/app 3 4 5 6 7 8 9 10 RUN mkdir -p target/dependency && (cd target/dependency; jar -xf ../*.jar) 11 12 # run stage 13 FROM eclipse-temurin:17-jdk-alpine 14 15 RUN mkdir -p target/dependency && (cd target/dependency; jar -xf ../*.jar) # build stage 1 FROM eclipse-temurin:17-jdk-alpine as build 2 WORKDIR /workspace/app 3 4 COPY mvnw . 5 COPY .mvn .mvn 6 COPY pom.xml . 7 COPY src src 8 9 RUN ./mvnw install -DskipTests 10 11 12 # run stage 13 FROM eclipse-temurin:17-jdk-alpine 14 15 # build stage 1 FROM eclipse-temurin:17-jdk-alpine as build 2 WORKDIR /workspace/app 3 4 COPY mvnw . 5 COPY .mvn .mvn 6 COPY pom.xml . 7 COPY src src 8 9 RUN ./mvnw install -DskipTests 10 RUN mkdir -p target/dependency && (cd target/dependency; jar -xf ../*.jar) 11 12 # run stage 13 FROM eclipse-temurin:17-jdk-alpine 14 15 ARG DEPENDENCY=/workspace/app/target/dependency COPY --from=build ${DEPENDENCY}/BOOT-INF/lib /app/lib COPY --from=build ${DEPENDENCY}/META-INF /app/META-INF COPY --from=build ${DEPENDENCY}/BOOT-INF/classes /app RUN ./mvnw install -DskipTests 10 RUN mkdir -p target/dependency && (cd target/dependency; jar -xf ../*.jar) 11 12 # run stage 13 FROM eclipse-temurin:17-jdk-alpine 14 15 RUN addgroup -S demo && adduser -S demo -G demo 16 USER demo 17 18 VOLUME /tmp 19 20 21 22 23 ENTRYPOINT ["java","-cp","app:app/ lib/*","hello.Application"] 24 11.5 ø Dockerfile
  • 21. Le Hello World Spring Boot, selon Spring Boot E spring.io/guides # build stage FROM eclipse-temurin:17-jdk-alpine as build WORKDIR /workspace/app COPY mvnw . COPY .mvn .mvn COPY pom.xml . COPY src src RUN ./mvnw install -DskipTests RUN mkdir -p target/dependency && (cd target/dependency; jar -xf ../*.jar) # run stage FROM eclipse-temurin:17-jdk-alpine 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 # build stage # run stage 1 FROM eclipse-temurin:17-jdk-alpine as build 2 WORKDIR /workspace/app 3 4 COPY mvnw . 5 COPY .mvn .mvn 6 COPY pom.xml . 7 COPY src src 8 9 RUN ./mvnw install -DskipTests 10 RUN mkdir -p target/dependency && (cd target/dependency; jar -xf ../*.jar) 11 12 13 FROM eclipse-temurin:17-jdk-alpine 14 15 COPY mvnw . COPY .mvn .mvn COPY pom.xml . COPY src src RUN ./mvnw install -DskipTests # build stage 1 FROM eclipse-temurin:17-jdk-alpine as build 2 WORKDIR /workspace/app 3 4 5 6 7 8 9 10 RUN mkdir -p target/dependency && (cd target/dependency; jar -xf ../*.jar) 11 12 # run stage 13 FROM eclipse-temurin:17-jdk-alpine 14 15 RUN mkdir -p target/dependency && (cd target/dependency; jar -xf ../*.jar) # build stage 1 FROM eclipse-temurin:17-jdk-alpine as build 2 WORKDIR /workspace/app 3 4 COPY mvnw . 5 COPY .mvn .mvn 6 COPY pom.xml . 7 COPY src src 8 9 RUN ./mvnw install -DskipTests 10 11 12 # run stage 13 FROM eclipse-temurin:17-jdk-alpine 14 15 # build stage 1 FROM eclipse-temurin:17-jdk-alpine as build 2 WORKDIR /workspace/app 3 4 COPY mvnw . 5 COPY .mvn .mvn 6 COPY pom.xml . 7 COPY src src 8 9 RUN ./mvnw install -DskipTests 10 RUN mkdir -p target/dependency && (cd target/dependency; jar -xf ../*.jar) 11 12 # run stage 13 FROM eclipse-temurin:17-jdk-alpine 14 15 # build stage 1 FROM eclipse-temurin:17-jdk-alpine as build 2 WORKDIR /workspace/app 3 4 COPY mvnw . 5 COPY .mvn .mvn 6 COPY pom.xml . 7 COPY src src 8 9 RUN ./mvnw install -DskipTests 10 RUN mkdir -p target/dependency && (cd target/dependency; jar -xf ../*.jar) 11 12 # run stage 13 FROM eclipse-temurin:17-jdk-alpine 14 15 ENTRYPOINT ["java","-cp","app:app/ lib/*","hello.Application"] RUN ./mvnw install -DskipTests 10 RUN mkdir -p target/dependency && (cd target/dependency; jar -xf ../*.jar) 11 12 # run stage 13 FROM eclipse-temurin:17-jdk-alpine 14 15 RUN addgroup -S demo && adduser -S demo -G demo 16 USER demo 17 18 VOLUME /tmp 19 ARG DEPENDENCY=/workspace/app/target/dependency 20 COPY --from=build ${DEPENDENCY}/BOOT-INF/lib /app/lib 21 COPY --from=build ${DEPENDENCY}/META-INF /app/META-INF 22 COPY --from=build ${DEPENDENCY}/BOOT-INF/classes /app 23 24 11.6 ø Dockerfile
  • 22. L'instant philosophie Est-ce que ce Dockerfile était parfait ? Est-ce qu'on attend d'un·e développeur·euse l'écriture d'un tel Dockerfile ? 12
  • 23. Quel est le problème avec les Dockerfile ? 13
  • 24. Ce que pense Darren Shepherd (former @Rancher_Labs, k3s creator) Darren Shepherd @ibuildthecloud · Follow So issues I have 1. Caching. I've been told this is hard. I believe there is stupider and more effective ways to (not) do it 2. Layers are soooo 2018 3. Multi stage is cool and all, but you really only need two stages (build env, run env) 4. COPY is kinda pointless. Darren Shepherd @ibuildthecloud I don't know if I can shake the urge to try to build a better Dockerfile. 9:25 AM · Jun 27, 2023 43 Reply Copy link Read 6 replies Darren Shepherd · Jun 27, 2023 @ibuildthecloud · Follow Replying to @ibuildthecloud Layers just suck. They've never really been used effectively and cause tons of cache issues. I'm not fundamentally opposed to layers, but maybe just 3. I can do 3. Darren Shepherd @ibuildthecloud · Follow You really can't build a properly good docker image without multi stage because you don't want your compiler in the final image. I think a better UX can be built assuming you basically always want to stages: build and run. 9:34 AM · Jun 27, 2023 8 Reply Copy link Read 6 replies 14
  • 25. Écrire un ø Dockerfile Image de base, Runtime / Version ( FROM ) Optimiser les layers ( RUN ) Script de démarrage ( ENTRYPOINT ) Configuration ( ENV ) Sécurité User non-root ( USER ) Versions des packages / runtime à jour Pas de code source dans l'image finale Pouvoir patcher les images en cas de nouvelle faille Pas de secrets 15
  • 26. Comment font les développeurs qui doivent écrire un ø Dockerfile ? _Au pire : Stackoverflow, ChatGPT, ou un tutoriel random SBof : le Dockerfile de Spring Boot, ou NodeJs DMieux : ils sont experts Docker, ou un Ops écrit le Dockerfile avec eux 16
  • 27. Et c'est pire en entreprise Chaque projet a son propre Dockerfile , forcément différent des autres Bienvenue en enfer m Quand les normes évoluent, ouvrir des change-request sur tous les projets de l'entreprise pour mettre à jour les Dockerfile 17
  • 33. Images OCI ? øDocker On parle d'image OCI depuis 2015 (Open Container Initiative) Normalisé : github.com/opencontainers/image-spec 19.4
  • 34. La vision qu'on a souvent : Les layers : ubuntu:jammy 9dbb3ddf83 eclipse-temurin:17-jdk 2ec73b48ae mon-appli:1 d1669123f2 distrib + runtime/middleware + code 20
  • 35. JSON + tar.gz = ‡ On appelle ça un Manifest d'image { "schemaVersion": 2, "mediaType": "application/vnd.docker.distribution.manifest.v2+json", "layers": [ { "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip", "size": 30430275, "digest": "sha256:d1669123f28121211977ed38e663dca1a397c0c001e5386598b96c8 }, { "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip", "size": 17038759, "digest": "sha256:2ec73b48ae406646223453ca41d5d6b7cb739853fb7a44f15d35a31 }, { 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 21 ✈ manifest.json
  • 36. JSON + tar.gz = ‡ On appelle ça un Manifest d'image { "schemaVersion": 2, "mediaType": "application/vnd.docker.distribution.manifest.v2+json", "layers": [ { "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip", "size": 30430275, "digest": "sha256:d1669123f28121211977ed38e663dca1a397c0c001e5386598b96c8 }, { "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip", "size": 17038759, "digest": "sha256:2ec73b48ae406646223453ca41d5d6b7cb739853fb7a44f15d35a31 }, { 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 "layers": [ { "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip", "size": 30430275, "digest": "sha256:d1669123f28121211977ed38e663dca1a397c0c001e5386598b96c8 }, { "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip", "size": 17038759, "digest": "sha256:2ec73b48ae406646223453ca41d5d6b7cb739853fb7a44f15d35a31 }, { "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip", "size": 192587566, "digest": "sha256:9dbb3ddf83e9096c0e2f32bfa93d16285d2e9586b1a9aa25e33d04c yp pp j , 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 21.1 ✈ manifest.json
  • 37. JSON + tar.gz = ‡ On appelle ça un Manifest d'image { "schemaVersion": 2, "mediaType": "application/vnd.docker.distribution.manifest.v2+json", "layers": [ { "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip", "size": 30430275, "digest": "sha256:d1669123f28121211977ed38e663dca1a397c0c001e5386598b96c8 }, { "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip", "size": 17038759, "digest": "sha256:2ec73b48ae406646223453ca41d5d6b7cb739853fb7a44f15d35a31 }, { 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 "layers": [ { "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip", "size": 30430275, "digest": "sha256:d1669123f28121211977ed38e663dca1a397c0c001e5386598b96c8 }, { "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip", "size": 17038759, "digest": "sha256:2ec73b48ae406646223453ca41d5d6b7cb739853fb7a44f15d35a31 }, { { 1 "schemaVersion": 2, 2 "mediaType": "application/vnd.docker.distribution.manifest.v2+json", 3 4 5 6 7 8 9 10 11 12 13 14 15 "config": { "mediaType": "application/vnd.docker.container.image.v1+json", "size": 6305, "digest": "sha256:50440189b0f4cd6264c2f03f92acf4772680d864e3a0d422ef4c46373 } size : 192587566, 17 "digest": "sha256:9dbb3ddf83e9096c0e2f32bfa93d16285d2e9586b1a9aa25e33d04c 18 }, 19 { 20 "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip", 21 "size": 175, 22 "digest": "sha256:08d2567dd626029019cc940915699f23b075d05189d99319604fbda 23 } 24 ], 25 26 27 28 29 30 } 31 21.2 ✈ manifest.json
  • 38. La configuration aussi fait partie de l'image OCI ! architecture / OS variables d'environnements users labels commandes / entrypoints ports 22
  • 39. eclipse-temurin:17.0.7_7-jdk { "architecture": "amd64", "config": { "Hostname": "", "Domainname": "", "User": "", "AttachStdin": false, "AttachStdout": false, "AttachStderr": false, "Tty": false, "OpenStdin": false, "StdinOnce": false, "Env": [ "PATH=/opt/java/openjdk/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr "JAVA HOME=/opt/java/openjdk", 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 23 Ô config.json
  • 40. eclipse-temurin:17.0.7_7-jdk { "architecture": "amd64", "config": { "Hostname": "", "Domainname": "", "User": "", "AttachStdin": false, "AttachStdout": false, "AttachStderr": false, "Tty": false, "OpenStdin": false, "StdinOnce": false, "Env": [ "PATH=/opt/java/openjdk/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr "JAVA HOME=/opt/java/openjdk", 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 "architecture": "amd64", { 1 2 "config": { 3 "Hostname": "", 4 "Domainname": "", 5 "User": "", 6 "AttachStdin": false, 7 "AttachStdout": false, 8 "AttachStderr": false, 9 "Tty": false, 10 "OpenStdin": false, 11 "StdinOnce": false, 12 "Env": [ 13 "PATH=/opt/java/openjdk/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr 14 "JAVA HOME=/opt/java/openjdk", 15 23.1 Ô config.json
  • 41. eclipse-temurin:17.0.7_7-jdk { "architecture": "amd64", "config": { "Hostname": "", "Domainname": "", "User": "", "AttachStdin": false, "AttachStdout": false, "AttachStderr": false, "Tty": false, "OpenStdin": false, "StdinOnce": false, "Env": [ "PATH=/opt/java/openjdk/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr "JAVA HOME=/opt/java/openjdk", 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 "architecture": "amd64", { 1 2 "config": { 3 "Hostname": "", 4 "Domainname": "", 5 "User": "", 6 "AttachStdin": false, 7 "AttachStdout": false, 8 "AttachStderr": false, 9 "Tty": false, 10 "OpenStdin": false, 11 "StdinOnce": false, 12 "Env": [ 13 "PATH=/opt/java/openjdk/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr 14 "JAVA HOME=/opt/java/openjdk", 15 "Env": [ "PATH=/opt/java/openjdk/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr "JAVA_HOME=/opt/java/openjdk", "LANG=en_US.UTF-8", "LANGUAGE=en_US:en", "LC_ALL=en_US.UTF-8", "JAVA_VERSION=jdk-17.0.7+7" ], AttachStderr : false, 9 "Tty": false, 10 "OpenStdin": false, 11 "StdinOnce": false, 12 13 14 15 16 17 18 19 20 "Cmd": [ 21 "jshell" 22 ], 23 "Image": "sha256:1dcdc9129900e8da6859de2013f135eb56cc4b67e04ceda95e957b9555 24 23.2 Ô config.json
  • 42. eclipse-temurin:17.0.7_7-jdk { "architecture": "amd64", "config": { "Hostname": "", "Domainname": "", "User": "", "AttachStdin": false, "AttachStdout": false, "AttachStderr": false, "Tty": false, "OpenStdin": false, "StdinOnce": false, "Env": [ "PATH=/opt/java/openjdk/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr "JAVA HOME=/opt/java/openjdk", 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 "architecture": "amd64", { 1 2 "config": { 3 "Hostname": "", 4 "Domainname": "", 5 "User": "", 6 "AttachStdin": false, 7 "AttachStdout": false, 8 "AttachStderr": false, 9 "Tty": false, 10 "OpenStdin": false, 11 "StdinOnce": false, 12 "Env": [ 13 "PATH=/opt/java/openjdk/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr 14 "JAVA HOME=/opt/java/openjdk", 15 "Env": [ "PATH=/opt/java/openjdk/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr "JAVA HOME=/opt/java/openjdk", { 1 "architecture": "amd64", 2 "config": { 3 "Hostname": "", 4 "Domainname": "", 5 "User": "", 6 "AttachStdin": false, 7 "AttachStdout": false, 8 "AttachStderr": false, 9 "Tty": false, 10 "OpenStdin": false, 11 "StdinOnce": false, 12 13 14 15 "User": "", { 1 "architecture": "amd64", 2 "config": { 3 "Hostname": "", 4 "Domainname": "", 5 6 "AttachStdin": false, 7 "AttachStdout": false, 8 "AttachStderr": false, 9 "Tty": false, 10 "OpenStdin": false, 11 "StdinOnce": false, 12 "Env": [ 13 "PATH=/opt/java/openjdk/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr 14 "JAVA HOME=/opt/java/openjdk", 15 23.3 Ô config.json
  • 43. eclipse-temurin:17.0.7_7-jdk { "architecture": "amd64", "config": { "Hostname": "", "Domainname": "", "User": "", "AttachStdin": false, "AttachStdout": false, "AttachStderr": false, "Tty": false, "OpenStdin": false, "StdinOnce": false, "Env": [ "PATH=/opt/java/openjdk/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr "JAVA HOME=/opt/java/openjdk", 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 "architecture": "amd64", { 1 2 "config": { 3 "Hostname": "", 4 "Domainname": "", 5 "User": "", 6 "AttachStdin": false, 7 "AttachStdout": false, 8 "AttachStderr": false, 9 "Tty": false, 10 "OpenStdin": false, 11 "StdinOnce": false, 12 "Env": [ 13 "PATH=/opt/java/openjdk/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr 14 "JAVA HOME=/opt/java/openjdk", 15 "Env": [ "PATH=/opt/java/openjdk/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr "JAVA HOME=/opt/java/openjdk", { 1 "architecture": "amd64", 2 "config": { 3 "Hostname": "", 4 "Domainname": "", 5 "User": "", 6 "AttachStdin": false, 7 "AttachStdout": false, 8 "AttachStderr": false, 9 "Tty": false, 10 "OpenStdin": false, 11 "StdinOnce": false, 12 13 14 15 "User": "", { 1 "architecture": "amd64", 2 "config": { 3 "Hostname": "", 4 "Domainname": "", 5 6 "AttachStdin": false, 7 "AttachStdout": false, 8 "AttachStderr": false, 9 "Tty": false, 10 "OpenStdin": false, 11 "StdinOnce": false, 12 "Env": [ 13 "PATH=/opt/java/openjdk/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr 14 "JAVA HOME=/opt/java/openjdk", 15 "Labels": { "org.opencontainers.image.ref.name": "ubuntu", "org.opencontainers.image.version": "22.04" } ], 23 "Image": "sha256:1dcdc9129900e8da6859de2013f135eb56cc4b67e04ceda95e957b9555 24 "Volumes": null, 25 "WorkingDir": "", 26 "Entrypoint": null, 27 "OnBuild": null, 28 29 30 31 32 }, 33 "created": "2023-06-02T01:44:46.577735785Z", 34 "docker_version": "20.10.23", 35 "os": "linux", 36 "rootfs": { 37 "type": "layers" 38 23.4 Ô config.json
  • 44. eclipse-temurin:17.0.7_7-jdk { "architecture": "amd64", "config": { "Hostname": "", "Domainname": "", "User": "", "AttachStdin": false, "AttachStdout": false, "AttachStderr": false, "Tty": false, "OpenStdin": false, "StdinOnce": false, "Env": [ "PATH=/opt/java/openjdk/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr "JAVA HOME=/opt/java/openjdk", 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 "architecture": "amd64", { 1 2 "config": { 3 "Hostname": "", 4 "Domainname": "", 5 "User": "", 6 "AttachStdin": false, 7 "AttachStdout": false, 8 "AttachStderr": false, 9 "Tty": false, 10 "OpenStdin": false, 11 "StdinOnce": false, 12 "Env": [ 13 "PATH=/opt/java/openjdk/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr 14 "JAVA HOME=/opt/java/openjdk", 15 "Env": [ "PATH=/opt/java/openjdk/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr "JAVA HOME=/opt/java/openjdk", { 1 "architecture": "amd64", 2 "config": { 3 "Hostname": "", 4 "Domainname": "", 5 "User": "", 6 "AttachStdin": false, 7 "AttachStdout": false, 8 "AttachStderr": false, 9 "Tty": false, 10 "OpenStdin": false, 11 "StdinOnce": false, 12 13 14 15 "User": "", { 1 "architecture": "amd64", 2 "config": { 3 "Hostname": "", 4 "Domainname": "", 5 6 "AttachStdin": false, 7 "AttachStdout": false, 8 "AttachStderr": false, 9 "Tty": false, 10 "OpenStdin": false, 11 "StdinOnce": false, 12 "Env": [ 13 "PATH=/opt/java/openjdk/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr 14 "JAVA HOME=/opt/java/openjdk", 15 { 1 "architecture": "amd64", 2 "config": { 3 "Hostname": "", 4 "Domainname": "", 5 "User": "", 6 "AttachStdin": false, 7 "AttachStdout": false, 8 "AttachStderr": false, 9 "Tty": false, 10 "OpenStdin": false, 11 "StdinOnce": false, 12 "Env": [ 13 "PATH=/opt/java/openjdk/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr 14 "JAVA HOME=/opt/java/openjdk", 15 "Cmd": [ "jshell" ], "JAVA_HOME=/opt/java/openjdk", 15 "LANG=en_US.UTF-8", 16 "LANGUAGE=en_US:en", 17 "LC_ALL=en_US.UTF-8", 18 "JAVA_VERSION=jdk-17.0.7+7" 19 ], 20 21 22 23 "Image": "sha256:1dcdc9129900e8da6859de2013f135eb56cc4b67e04ceda95e957b9555 24 "Volumes": null, 25 "WorkingDir": "", 26 "Entrypoint": null, 27 "OnBuild": null, 28 "Labels": { 29 23.5 Ô config.json
  • 45. L'instant philosophie Heureusement qu'ils n'ont pas choisi YAML 24
  • 46. docker image inspect ú docker image inspect eclipse-temurin:17.0.7_7-jdk | bat -l json # on parcours une image avec dive ! dive petclinic:dockerfile 25 > bash > bash
  • 47. Une image OCI Des fichiers tar.gz Chaque fichier a un digest sha256 De la configuration au format JSON 26
  • 48. Et si ? On pouvait générer tout ça ? On pourrait créer des images OCI, sans avoir besoin de øDocker ou d'un Dockerfile ! 27
  • 49. L'instant philosophie ça veut aussi dire, qu'on peut modifier une image, juste en allant modifier son manifest 28
  • 51. 30
  • 52. 31
  • 53. Buildpacks Concept par Heroku en 2011 pour leur propre besoin de PaaS multi-langage. CNB (Cloud Native Buildpacks) initié en 2018, et a rejoint la CNCF (Cloud Native Computing Foundation) en 2018 en "Incubating". 32
  • 55. builder construit une image buildpack contribue à une ou plusieurs layers dans la construction 34
  • 56. Un buildpack est composé de 2 binaires : /bin/detect : indique si le buildpack doit être activé /bin/build : contribue à la construction d'une ou plusieurs layers 35
  • 57. Le builder contient des scripts lifecycle : 1. Code source dans un répertoire /workspace 2. Interroge chaque buildpack avec /bin/detect 3. Exécute tous les buildpacks qui doivent être exécutés 4. Chaque buildpack contribue une ou plusieurs layers dans /layer 5. Les layers dans /layer sont exportées pour créer une image OCI ! 36
  • 58. 37
  • 65. Mais aussi Le builder peut charger du cache depuis un registry OCI ( .m2/ , node_modules/ , ...) Les layers peuvent être reproductibles Le builder ne s'exécute pas en root Le builder est une image OCI ! 38
  • 66. Outillage Le CLI pack permet d'exécuter des builders, pour construire des images. # installation du CLI avec apt sudo add-apt-repository ppa:cncf-buildpacks/pack-cli sudo apt-get update sudo apt-get install pack-cli # premiers secours pack --help # construction d'une image OCI ! pack build ma-jolie-image --builder paketobuildpacks/builder:base 39 > bash > bash > bash
  • 67. Les builders de la communauté Paketo (Cloud-Foundry / VMWare + Pivotal) # paketo-base docker container run --rm -t paketobuildpacks/builder:base ls /cnb/buildpacks # paketo-tiny construit des image distroless docker container run --rm -t paketobuildpacks/builder:tiny ls /cnb/buildpacks 40 > bash > bash
  • 68. Les builders de la communauté Heroku Google # heroku docker container run --rm -t heroku/builder:22 ls /cnb/buildpacks # google docker container run --rm -t gcr.io/buildpacks/builder:google-22 ls /cnb/buildpacks 41 > bash > bash
  • 69. Construction d'image ! # construction d'une image pack build petclinic:demo --builder paketobuildpacks/builder:base # parcours des layers construite avec dive dive petclinic:demo # inspection de l'image docker image inspect petclinic:demo | bat -l json 42 > bash > bash > bash
  • 70. L'image produite ubuntu:bionic ca-certificates jdk SBOM /app/BOOT-INF/lib /app/META-INF /app/BOOT-INF/classes launcher metadata Respecte les bonnes pratiques de layering de Spring Boot Est plus légère que celle proposée par Spring Boot REPOSITORY TAG IMAGE ID SIZE CREATED petclinic dockerfile 3c06306a 409MB 7 minute petclinic demo c3448bd3 315MB 43 years 43 > bash
  • 71. Une image produite pour une appli NodeJS ubuntu:bionic ca-certificates node runtime node_modules SBOM /app launcher metadata 44
  • 72. Qui l'utilise en production ? Est-ce que c'est mature ? 45
  • 73. Qui l'utilise en production ? Est-ce que c'est mature ? Google App Engine 45.1
  • 74. Qui l'utilise en production ? Est-ce que c'est mature ? Google App Engine Google Cloud Run 45.2
  • 75. Qui l'utilise en production ? Est-ce que c'est mature ? Google App Engine Google Cloud Run Google Cloud Functions 45.3
  • 76. Qui l'utilise en production ? Est-ce que c'est mature ? Google App Engine Google Cloud Run Google Cloud Functions Azure Container Apps 45.4
  • 77. Qui l'utilise en production ? Est-ce que c'est mature ? Google App Engine Google Cloud Run Google Cloud Functions Azure Container Apps Gitlab Auto DevOps 45.5
  • 78. Qui l'utilise en production ? Est-ce que c'est mature ? Google App Engine Google Cloud Run Google Cloud Functions Azure Container Apps Gitlab Auto DevOps KNative 45.6
  • 79. Qui l'utilise en production ? Est-ce que c'est mature ? Google App Engine Google Cloud Run Google Cloud Functions Azure Container Apps Gitlab Auto DevOps KNative Dokku 45.7
  • 80. Qui l'utilise en production ? Est-ce que c'est mature ? Google App Engine Google Cloud Run Google Cloud Functions Azure Container Apps Gitlab Auto DevOps KNative Dokku Spring Boot (mvn spring- 45.8
  • 81. Qui l'utilise en production ? Est-ce que c'est mature ? Google App Engine Google Cloud Run Google Cloud Functions Azure Container Apps Gitlab Auto DevOps KNative Dokku Spring Boot (mvn spring- Riff (Netlify) 45.9
  • 83. En vrac Plus besoin de maintenir un Dockerfile Gestion de cache, réutilisation de layers existantes Modularité 47
  • 84. SBoM Software Bill of Materials Chaque buildpack contribue à la construction d'un SBoM dans une layer dédiée C'est vos RSSI et vos RSO qui vont être contents y 48
  • 85. Reproductibilité des builds ? E À partir du même code source, produit strictement le même binaire / la même image, avec le même digest sha256 ! Nécessite de mettre à "0" les dates des fichiers. Ça évite de produire de "nouvelles" layers si du code n'a pas changé (exemple, les libs) "Created": "1980-01-01T00:00:01Z" REPOSITORY TAG IMAGE ID CREATED SIZE petclinic demo c3448bd3501d 43 years ago 315MB 49 {} JSON > bash
  • 86. Reproductibilité des builds ? E # pull d'une image construite précédemment docker image pull rg.fr-par.scw.cloud/sunny-tech-buildpacks/petclinic:paketo-base # comparaison des layers docker image inspect petclinic:demo | jq '.[].RootFS' docker image inspect rg.fr-par.scw.cloud/sunny-tech-buildpacks/petclinic:paketo-bas diff -s <(docker image inspect petclinic:demo | jq '.[].RootFS') <(docker image ins 50 > bash > bash
  • 87. Reproductibilité des builds ? ` Les images buildées sur une CI et sur le poste développeur ont la même signature ! Les images buildées par deux pipelines de CI consécutifs sont identiques ! 51
  • 88. Le rebase d'image Oui, ça veut bien dire ce que vous imaginez ! ubuntu:jammy 9dbb3ddf83 eclipse-temurin:17-jdk 2ec73b48ae mon appli d1669123f2 eclipse-temurin:20-jdk 40915699f2 mon appli d1669123f2 ubuntu:jammy 9dbb3ddf83 52
  • 89. Le rebase d'image pack rebase petclinic:demo --run-image <new-base-image> 53 > bash
  • 90. Le rebase d'image Se fait au niveau du ✈Manifest Implémenté par la plupart des builders sur la couche "distribution" Permet de modifier les layers basses d'une image, sans avoir besoin de la reconstruire Permet de patcher rapidement une image, sans rebuild 54
  • 91. Créer son propre builder  Choisir son image de base Réutiliser des buildpacks existants Implémenter les langages manquants 55
  • 93. Les buildpacks c'est cool „ Un builder pour supporter tous vos langages Génère des SBOM pour votre RSSI/RSO préféré Gestion du cache intégrée Facile d'utilisation Implémente les bonnes pratiques de layering, sécurité Reproductibilité des builds ` Rebase d'images ` 57
  • 94. Mais... › Créer son propre builder, c'est compliqué Le CLI pack utilise Docker, ou Podman Mais y'a moyen d'exécuter un builder sans Docker : kpack tekton Customisation pas forcément évidente 58
  • 95. Merci pour votre attention ! Un petit feedback ? => Julien Wittouck - @CodeKaio 59