構建 Docker 映象的 N 個小技巧
構建映象的幾個小技巧
構建上下文
執行
docker build
命令時,當前的工作目錄被稱為構建上下文。預設情況下,Dockerfile 就位於該路徑下。也可以透過
-f
引數來指定 dockerfile ,但 docker 客戶端會將當前工作目錄下的所有檔案傳送到 docker 守護程式進行構建。
所以來說,當執行 docker build 進行構建映象時,當前目錄一定要
乾淨
,切記不要在家裡錄下建立一個 Dockerfile 緊接著
docker build
一把梭 ?。
正確做法是為專案建立一個資料夾,把構建映象時所需要的資源放在這個資料夾下。比如這樣:
mkdir projectcd !$vi Dockerfile# 編寫 Dockerfile
也可以透過
.dockerignore
檔案來忽略不需要的檔案傳送到 docker 守護程式
基礎映象
使用體積較小的基礎映象,比如
alpine
或者
debian:buster-slim
,像 openjdk 可以選用
openjdk:xxx-slim
,由於 openjdk 是基於 debian 的基礎映象構建的,所以向 debian 基礎映象一樣,後面帶個
slim
就是基於
debian:xxx-slim
映象構建的。
REPOSITORY TAG IMAGE ID CREATED SIZEdebian buster-slim e1af56d072b8 4 days ago 69.2MBalpine latest cc0abc535e36 8 days ago 5.59MB
不過需要注意的是,alpine 的 c 庫是
musl libc
,而不是正統的
glibc
,另外對於一些依賴
glibc
的大型專案,像 openjdk 、tomcat、rabbitmq 等都不建議使用 alpine 基礎映象,因為 musl libc 可能會導致 JVM 一些奇怪的問題。這也是為什麼 tomcat 官方沒有給出基礎映象是 alpine 的 Dockerfile 的原因。
國內軟體源
-
對於 alpine 基礎映象修改軟體源
echo "http://mirrors.huaweicloud.com/alpine/latest-stable/main/" > /etc/apk/repositories ;\echo "http://mirrors.huaweicloud.com/alpine/latest-stable/community/" >> /etc/apk/repositories ;\apk update ;
-
debian 基礎映象修改預設原件原始碼
sed -i 's/deb.debian.org/mirrors.huaweicloud.com/g' /etc/apt/sources.list ;\sed -i 's|security.debian.org/debian-security|mirrors.huaweicloud.com/debian-security|g' /etc/apt/sources.list ;\apt update ;\
-
Ubuntu 基礎映象修改預設原件原始碼
sed -i 's/archive.ubuntu.com/mirrors.huaweicloud.com/g' /etc/apt/sources.listapt update ;\
-
對於 CentOS ???
你確定要用 220MB 大小的基礎映象?
REPOSITORY TAG IMAGE ID CREATED SIZEcentos latest 0f3e07c0138f 3 months ago 220MB
時區設定
由於絕大多數基礎映象都是預設採用 UTC 的時區,與北京時間相差 8 個小時,這將會導致容器內的時間與北京時間不一致,因而會對一些應用造成一些影響,還會影響容器內日誌和監控的資料。
-e TZ=Asia/Shanghai
來設定容器內的時區。alpine
-
但對於 alpine 基礎映象無法透過 TZ 環境變數的方式設定時區,需要安裝 tzdata 來配置時區。
root@ubuntu:~/docke/alpine# docker run --rm -it -e TZ=Asia/Shanghai alpine dateThu Jan 2 03:37:44 UTC 2020
-
對於 alpine 基礎映象,可以在 RUN 指令後面追加上以下命令
apk add --no-cache tzdata ;\cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime ;\echo "Asia/Shanghai" > /etc/timezone ;\apk del tzdata ;\
-
透過 tzdate 設定時區
root@ubuntu:~/docke/alpine# docker build -t alpine:tz2 .Sending build context to Docker daemon 2.048kBStep 1/2 : FROM alpine ---> cc0abc535e36Step 2/2 : RUN set -xue ; echo "http://mirrors.huaweicloud.com/alpine/latest-stable/main/" > /etc/apk/repositories ; echo "http://mirrors.huaweicloud.com/alpine/latest-stable/community/" >> /etc/apk/repositories ; apk update ; apk add --no-cache tzdata ; cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime ; echo "Asia/Shanghai" > /etc/timezone ; apk del tzdata ---> Running in 982041a34dbf+ echo http://mirrors.huaweicloud.com/alpine/latest-stable/main/+ echo http://mirrors.huaweicloud.com/alpine/latest-stable/community/+ apk updatefetch http://mirrors.huaweicloud.com/alpine/latest-stable/main/x86_64/APKINDEX.tar.gzfetch http://mirrors.huaweicloud.com/alpine/latest-stable/community/x86_64/APKINDEX.tar.gzv3.11.2-11-gd5cdcefa20 [http://mirrors.huaweicloud.com/alpine/latest-stable/main/]v3.11.2-14-g973431591e [http://mirrors.huaweicloud.com/alpine/latest-stable/community/]OK: 11261 distinct packages available+ apk add --no-cache tzdatafetch http://mirrors.huaweicloud.com/alpine/latest-stable/main/x86_64/APKINDEX.tar.gzfetch http://mirrors.huaweicloud.com/alpine/latest-stable/community/x86_64/APKINDEX.tar.gz(1/1) Installing tzdata (2019c-r0)Executing busybox-1.31.1-r8.triggerOK: 9 MiB in 15 packages+ cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime+ echo Asia/Shanghai+ apk del tzdata(1/1) Purging tzdata (2019c-r0)Executing busybox-1.31.1-r8.triggerOK: 6 MiB in 14 packagesRemoving intermediate container 982041a34dbf ---> 3ec89f3e824dSuccessfully built 3ec89f3e824dSuccessfully tagged alpine:tz2root@ubuntu:~/docke/alpine# docker run --rm -it alpine:tz2 dateThu Jan 2 11:12:23 CST 2020
debian
-
透過啟動時設定環境變數指定時區
root@ubuntu:~/docke/alpine# docker run --rm -it -e TZ=Asia/Shanghai debian dateThu Jan 2 11:38:56 CST 2020
-
也可以再構建映象的時候複製時區檔案設定容器內時區
cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime ;\echo "Asia/shanghai" > /etc/timezone ;\
ubuntu
-
透過啟動時設定環境變數指定時區,發射失敗 ?,只能透過時區檔案來設定時區了。
root@ubuntu:~/docke/alpine# docker run --rm -it -e TZ=Asia/Shanghai debian date
Thu Jan 2 11:38:56 CST 2020
root@ubuntu:~/docke/alpine# ^debian^ubuntu
docker run --rm -it -e TZ=Asia/Shanghai ubuntu date
Thu Jan 2 03:44:13 Asia 2020
在這裡有個命令執行的小技巧,透過脫字元
^
來替換上一條命令中的 debian 為 ubuntu 然後執行相同的命令。
-
透過時區檔案來設定時區
apt update ;\apt install tzdata -y ;\cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime ;\echo "Asia/shanghai" > /etc/timezone ;\
儘量使用 URL 新增原始碼
git & wget source
然後
build
,最後
rm -rf source/
這三部放在一條 RUN 指令中,這樣就能避免原始碼新增到映象中而增大映象體積啦。-
專案官方的 Dockerfile
# centos 7
FROM centos:7
# 新增配置檔案
# add profiles
ADD conf/client.conf /etc/fdfs/
ADD conf/http.conf /etc/fdfs/
ADD conf/mime.types /etc/fdfs/
ADD conf/storage.conf /etc/fdfs/
ADD conf/tracker.conf /etc/fdfs/
ADD fastdfs.sh /home
ADD conf/nginx.conf /etc/fdfs/
ADD conf/mod_fastdfs.conf /etc/fdfs
# 新增原始檔
# add source code
ADD source/libfastcommon.tar.gz /usr/local/src/
ADD source/fastdfs.tar.gz /usr/local/src/
ADD source/fastdfs-nginx-module.tar.gz /usr/local/src/
ADD source/nginx-1.15.4.tar.gz /usr/local/src/
# Run
RUN yum install git gcc gcc-c++ make automake autoconf libtool pcre pcre-devel zlib zlib-devel openssl-devel wget vim -y \
&& mkdir /home/dfs \
&& cd /usr/local/src/ \
&& cd libfastcommon/ \
&& ./make.sh && ./make.sh install \
&& cd ../ \
&& cd fastdfs/ \
&& ./make.sh && ./make.sh install \
&& cd ../ \
&& cd nginx-1.15.4/ \
&& ./configure --add-module=/usr/local/src/fastdfs-nginx-module/src/ \
&& make && make install \
&& chmod +x /home/fastdfs.sh
# export config
VOLUME /etc/fdfs
EXPOSE 22122 23000 8888 80
ENTRYPOINT ["/home/fastdfs.sh"]
-
經過本人最佳化後的 Dockerfile
FROM alpine:3.10
RUN set -x \
&& echo "http://mirrors.huaweicloud.com/alpine/latest-stable/main/" > /etc/apk/repositories \
&& echo "http://mirrors.huaweicloud.com/alpine/latest-stable/community/" >> /etc/apk/repositories \
&& apk update \
&& apk add --no-cache --virtual .build-deps gcc libc-dev make perl-dev openssl-dev pcre-dev zlib-dev git \
&& mkdir -p /usr/local/src \
&& cd /usr/local/src \
&& git clone --depth 1 \
&& git clone --depth 1 \
&& git clone --depth 1 \
&& wget \
&& tar -xf nginx-1.15.4.tar.gz \
&& cd /usr/local/src/libfastcommon \
&& ./make.sh \
&& ./make.sh install \
&& cd /usr/local/src/fastdfs/ \
&& ./make.sh \
&& ./make.sh install \
&& cd /usr/local/src/nginx-1.15.4/ \
&& ./configure --add-module=/usr/local/src/fastdfs-nginx-module/src/ \
&& make && make install \
&& apk del .build-deps \
&& apk add --no-cache pcre-dev bash \
&& mkdir -p /home/dfs \
&& mv /usr/local/src/fastdfs/docker/dockerfile_network/fastdfs.sh /home \
&& mv /usr/local/src/fastdfs/docker/dockerfile_network/conf/* /etc/fdfs \
&& chmod +x /home/fastdfs.sh \
&& rm -rf /usr/local/src*
VOLUME /home/dfs
EXPOSE 22122 23000 8888 8080
CMD ["/home/fastdfs.sh"]
-
構建之後的對比
使用專案預設的 Dockerfile 進行構建的話,映象大小接近 500MB,而經過一些的最佳化,將所有的 RUN 指令合併為一條,最終構建出來的映象大小為 30MB。
REPOSITORY TAG IMAGE ID CREATED SIZEfastdfs alpine e855bd197dbe 10 seconds ago 29.3MBfastdfs debian e05ca1616604 20 minutes ago 103MBfastdfs centos c1488537c23c 30 minutes ago 483MB
使用虛擬編譯環境
對於只在編譯過程中使用到的依賴,我們可以將這些依賴安裝在虛擬環境中,編譯完成之後可以一併刪除這些依賴,比如 alpine 中可以使用
apk add --no-cache --virtual .build-deps
,後面加上需要安裝的相關依賴。
apk add --no-cache --virtual .build-deps gcc libc-dev make perl-dev openssl-dev pcre-dev zlib-dev git
構建完成之後可以使用 apk del .build-deps 命令,一併將這些編譯依賴全部刪除。
需要注意的是,.build-deps 後面接的是編譯時以來的軟體包,並不是所有的編譯依賴都可以刪除,不要把執行時的依賴包接在後面,最好單獨 add 一下。
最小化層數
docker 在 1.10 以後,只有
RUN、COPY 和 ADD
指令會建立層,其他指令會建立臨時的中間映象,但是不會直接增加構建的映象大小了。
前文提到了建議使用 git 或者 wget 的方式來將檔案打入到映象當中,但如果我們必須要使用 COPY 或者 ADD 指令呢?
還是拿 FastDFS 為例:
# centos 7
FROM centos:7
# 新增配置檔案
# add profiles
ADD conf/client.conf /etc/fdfs/
ADD conf/http.conf /etc/fdfs/
ADD conf/mime.types /etc/fdfs/
ADD conf/storage.conf /etc/fdfs/
ADD conf/tracker.conf /etc/fdfs/
ADD fastdfs.sh /home
ADD conf/nginx.conf /etc/fdfs/
ADD conf/mod_fastdfs.conf /etc/fdfs
# 新增原始檔
# add source code
ADD source/libfastcommon.tar.gz /usr/local/src/
ADD source/fastdfs.tar.gz /usr/local/src/
ADD source/fastdfs-nginx-module.tar.gz /usr/local/src/
ADD source/nginx-1.15.4.tar.gz /usr/local/src/
src.tar.gz
然後透過 ADD 的方式把檔案新增到當中去,然後在 RUN 指令後使用
mv
命令把檔案移動到指定的位置。這樣僅僅一條 ADD 和 RUN 指令取代掉了 12 個 ADD 指令。FROM alpine:3.10COPY src.tar.gz /usr/local/src.tar.gzRUN set -xe \ && apk add --no-cache --virtual .build-deps gcc libc-dev make perl-dev openssl-dev pcre-dev zlib-dev tzdata \ && cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \ && tar -xvf /usr/local/src.tar.gz -C /usr/local \ && mv /usr/local/src/conf/fastdfs.sh /home/fastdfs/ \ && mv /usr/local/src/conf/* /etc/fdfs \ && chmod +x /home/fastdfs/fastdfs.sh \ && rm -rf /usr/local/src/* /var/cache/apk/* /tmp/* /var/tmp/* $HOME/.cacheVOLUME /var/fdfs
其他最小化層數無非就是把構建專案的整個步驟弄成一條 RUN 指令,不過多條命令合併可以使用
&&
或者
;
這兩者都可以,不過據我在 docker hub 上的所見所聞,使用
;
的居多,尤其是官方的 Dockerfile。
文章略有精 簡。
文章轉載: https://blog.k8s.li/dockerfile-tips.html
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70013542/viewspace-2929720/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 構建 Docker 映象的 N 個小技巧,運維工程師看過來Docker運維工程師
- 構建映象的幾個小技巧
- 構建Docker幾個小技巧Docker
- docker構建映象Docker
- docker 構建自己的映象Docker
- Docker映象構建(五)Docker
- docker構建supervisor映象Docker
- Docker 構建 kubectl 映象Docker
- Docker映象構建原理解析(不裝docker也能構建映象)Docker
- 構建更小的容器映象的技巧
- Docker 映象構建之 DockerfileDocker
- 怎樣去構建一個優質的Docker容器映象Docker
- Docker 分階段構建映象Docker
- Docker 構建多平臺映象Docker
- Docker構建多平臺映象Docker
- Docker 構建PHP 映象環境DockerPHP
- Docker 映象分階段構建Docker
- 不用安裝docker也能構建docker映象Docker
- 三個技巧幫助Docker映象瘦身Docker
- SpringBoot 構建 Docker 映象的最佳 3 種方式Spring BootDocker
- 製作一個能構建 dotnet AOT 的 gitlab runner 的 Debian docker 映象GitlabDocker
- 製作一個能構建 dotnet AOT 的 gitlab ruuner 的 Debian docker 映象GitlabDocker
- docker映象構建libreoffice轉換檔案Docker
- Docker容器 關於映象構建的安全問題Docker
- 構建API的7個技巧API
- Docker從零構建php-nginx-alpine映象DockerPHPNginx
- 構建 Go 應用 docker 映象的十八種姿勢GoDocker
- 從0開始構建一個瀚高資料庫Docker映象資料庫Docker
- apisix閘道器-構建docker映象構建及外掛化開發APIDocker
- Docker映象的構建以及資料卷和埠對映Docker
- Jib構建你的第一個java映象Java
- 使用Docker buildx 為 .NET 構建多平臺映象DockerUI
- 使用 Docker 開發 - 使用多階段構建映象Docker
- docker:映象構建、倉庫、壓縮、匯入 二Docker
- 10 個最佳化技巧,減少 Docker 映象大小【轉】Docker
- Java(SpringBoot)專案打包(構建)成`Docker`映象的幾種方式JavaSpring BootDocker
- Jenkins中構建(Build)Docker映象時出現permission deniedJenkinsUIDocker
- Docker映象構建:技術深度解析與實踐指南Docker