動機
看看寫Dockerfile的注意事項
目標
- 減小Image的大小
- 盡量使用cache
- 讓環境一致
COPY或RUN一次就會多一層layer,所以
把可以整合在同一句的RUN整合在同一句
Before
RUN apt update
RUN apt install -y ...
After
RUN apt update && apt install -y ...
只COPY需要的東西
Before
COPY . /app
After
COPY file1 file2 ... /app
把不常變動的放前面
只要docker看到這句的cache失效 就會把後面的所有指令都重跑一遍 Before
COPY file1 file2 ... /app
RUN apt update && apt install -y ...
After
RUN apt update && apt install -y ...
COPY file1 file2 ... /app
減少cache,只放真的需要的東西
移除不需要的dep & 清除apt快取
Before
RUN apt update && apt install -y ... vim
After
RUN apt update && apt install -y --no-install-recommends ... && rm -rf /var/lib/apt/lists/*
COPY file1 file2 ... /app
讓環境一致
如果有現成的就直接用,同時指定版本
Before
RUN apt update && apt install -y openjdk8 vim
After
FROM openjdk:8
COPY file1 file2 ... /app
剛剛好的權限
直接看例子
FROM maven:3.6.3-jdk-11 AS builder
WORKDIR /workdir/server
COPY pom.xml /workdir/server/pom.xml
RUN mvn dependency:go-offline
RUN mvn package
FROM openjdk:11-jre-slim
RUN addgroup -S java && adduser -S javauser -G java
USER javauser
EXPOSE 8080
COPY --from=builder /workdir/server/target/project-0.0.1-SNAPSHOT.jar /project-0.0.1-SNAPSHOT.jar
CMD ["java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "/project-0.0.1-SNAPSHOT.jar"]
區分不同的step(就是替dockerfile抽象)
multi-stege build (Docker 17.05後)
FROM openjdk:8 AS builder
...
FROM openjdk:8-jre-alpine
COPY --from=builder file1 file2 /app
CMD ["java", "-jar", "/app/app.jar"]
這個其實就是在一般PL會看到的副程式
不過因為Dockerfile沒有控制結構(條件判斷與迴圈) 所以沒有重複呼叫某塊code產生資料的需要 只要跑完要的資料就會在image中 因此只要有辦法碰到需要的Image就好 所以才有這種東西
不只是用自己的image,用其他的image也是ok的
COPY --from=nginx:latest /etc/nginx/nginx.conf /nginx.conf
只想build到某一層的Image也沒問題
docker build --target builder -t alexellis2/href-counter:latest .