歡迎訪問我的GitHub
https://github.com/zq2599/blog_demos
內容:所有原創文章分類彙總及配套原始碼,涉及Java、Docker、Kubernetes、DevOPS等;
本篇概覽
- 在《三分鐘:極速體驗JAVA版目標檢測(YOLO4)》一文中,我們們體驗了YOLO4強大的物體識別能力,如下圖:
- 如果您已看過《三分鐘:極速體驗JAVA版目標檢測(YOLO4)》,甚至動手實際操作過,您應該會對背後的技術細節感興趣,接下來就請隨欣宸一起動手實戰,從無到有將這個應用開發出來;
實戰內容
- 為了減少環境和軟體差異的影響,讓程式的執行除錯更簡單,也為了讓應用可以在容器環境執行,最終整個應用會被製作成docker映象,所以我們們的目標被設定為下面三項:
- 開發出java版的物體識別應用
- 將此應用製作成docker映象
- 在docker環境執行這個應用
- 基於上述目標,我們可以確定以下操作步驟:
- 準備好docker基礎映象
- 開發java應用
- 將java應用打包成package檔案,整合到基礎映象中,得到最終的java應用映象
- 整個流程如下圖所示:
- 本篇的目標就是上述第一步:準備好docker基礎映象
製作基礎映象
- 如果您有過製作java應用映象的經歷,一定會產生疑問:如下圖紅框所示,一般不都是把OpenJDK的官方映象作為基礎映象嗎?為啥要用一篇文章來講基礎映象的事情?
- 對於物體檢測的應用來說,OpenJDK的官方映象是不夠用的,因為用java實現檢測需要一個關鍵技術:javacv,在javacv執行過程中需要用到opencv的一些本地庫,因此需要在執行環境中安裝opencv
- 如下圖所示,一個應用自下而上由六部分構成,如果將底部的作業系統、JDK、OpenCV做成基礎映象就方便多了,我們們開發應用的時候只要需關注上面三層即可,而上面三層不就是個普通的maven工程嗎?
- 至此,聰明的您對接下來要做的事情應該很清楚了:編寫Dockerfile檔案用來製作映象,這個映象中要有CentOS7 + JDK1.8 + OpenCV4
分兩步走
- 我打算先做一個CentOS7 + JDK8的映象,在此基礎上再做一個整合了OpenCV的映象,這樣在一些不需要OpenCV的場景中,我還能單獨使用CentOS7 + JDK1.8的映象
- 分析完成,開始動手吧
CentOS7 + JDK8的映象
- 之所以選擇CentOS作為作業系統,是因為平時工作中最常用的就是它了
- 縱觀OpenJDK官方的各種映象,並沒有發現CentOS作為作業系統的,因此自己動手做一個吧,思路很簡單:找到OpenJDK的Dockerfile檔案,把它的基礎映象換成CentOS7.6即可
- 以下是Dockerfile的所有內容,可見核心是根據不同的作業系統下載檔案然後安裝,邏輯簡單清晰就不多說了:
FROM centos:7.6.1810
RUN set -eux; \
yum install -y \
gzip \
tar \
binutils \
freetype fontconfig \
;
ENV JAVA_HOME /usr/java/openjdk-8
ENV PATH $JAVA_HOME/bin:$PATH
# Default to UTF-8 file.encoding
ENV LANG C.UTF-8
RUN set -eux; \
\
arch="$(objdump="$(command -v objdump)" && objdump --file-headers "$objdump" | awk -F '[:,]+[[:space:]]+' '$1 == "architecture" { print $2 }')"; \
case "$arch" in \
'i386:x86-64') \
downloadUrl='https://github.com/AdoptOpenJDK/openjdk8-upstream-binaries/releases/download/jdk8u292-b10/OpenJDK8U-jdk_x64_linux_8u292b10.tar.gz'; \
;; \
'aarch64') \
downloadUrl='https://github.com/AdoptOpenJDK/openjdk8-upstream-binaries/releases/download/jdk8u292-b10/OpenJDK8U-jdk_aarch64_linux_8u292b10.tar.gz'; \
;; \
*) echo >&2 "error: unsupported architecture: '$arch'"; exit 1 ;; \
esac; \
\
curl -fL -o openjdk.tgz "$downloadUrl"; \
curl -fL -o openjdk.tgz.asc "$downloadUrl.sign"; \
\
export GNUPGHOME="$(mktemp -d)"; \
# pre-fetch Andrew Haley's (the OpenJDK 8 and 11 Updates OpenJDK project lead) key so we can verify that the OpenJDK key was signed by it
# (https://github.com/docker-library/openjdk/pull/322#discussion_r286839190)
# we pre-fetch this so that the signature it makes on the OpenJDK key can survive "import-clean" in gpg
gpg --batch --keyserver keyserver.ubuntu.com --recv-keys EAC843EBD3EFDB98CC772FADA5CD6035332FA671; \
# TODO find a good link for users to verify this key is right (https://mail.openjdk.java.net/pipermail/jdk-updates-dev/2019-April/000951.html is one of the only mentions of it I can find); perhaps a note added to https://adoptopenjdk.net/upstream.html would make sense?
# no-self-sigs-only: https://salsa.debian.org/debian/gnupg2/commit/c93ca04a53569916308b369c8b218dad5ae8fe07
gpg --batch --keyserver keyserver.ubuntu.com --keyserver-options no-self-sigs-only --recv-keys CA5F11C6CE22644D42C6AC4492EF8D39DC13168F; \
gpg --batch --list-sigs --keyid-format 0xLONG CA5F11C6CE22644D42C6AC4492EF8D39DC13168F \
| tee /dev/stderr \
| grep '0xA5CD6035332FA671' \
| grep 'Andrew Haley'; \
gpg --batch --verify openjdk.tgz.asc openjdk.tgz; \
rm -rf "$GNUPGHOME"; \
\
mkdir -p "$JAVA_HOME"; \
tar --extract \
--file openjdk.tgz \
--directory "$JAVA_HOME" \
--strip-components 1 \
--no-same-owner \
; \
rm openjdk.tgz*; \
\
rm -rf "$JAVA_HOME/jre/lib/security/cacerts"; \
# see "update-ca-trust" script which creates/maintains this cacerts bundle
ln -sT /etc/pki/ca-trust/extracted/java/cacerts "$JAVA_HOME/jre/lib/security/cacerts"; \
\
# https://github.com/oracle/docker-images/blob/a56e0d1ed968ff669d2e2ba8a1483d0f3acc80c0/OracleJava/java-8/Dockerfile#L17-L19
ln -sfT "$JAVA_HOME" /usr/java/default; \
ln -sfT "$JAVA_HOME" /usr/java/latest; \
for bin in "$JAVA_HOME/bin/"*; do \
base="$(basename "$bin")"; \
[ ! -e "/usr/bin/$base" ]; \
alternatives --install "/usr/bin/$base" "$base" "$bin" 20000; \
done; \
\
# basic smoke test
javac -version; \
java -version
- 寫完之後執行<font color="blue">docker build -t bolingcavalry/centos7.6-jdk8:0.0.1 .</font>即可生成映象,如果您有hub.docker.com的賬號,還可以將其推送到中央倉庫,給更多人使用
- 用history命令看看映象內容,詳情如下,合計五百多兆,已經不小了:
will@Mac-mini$ docker history bolingcavalry/centos7.6-jdk8:0.0.1
IMAGE CREATED CREATED BY SIZE COMMENT
a5dead4a6505 2 days ago /bin/sh -c set -eux; arch="$(objdump… 209MB
<missing> 2 days ago /bin/sh -c #(nop) ENV LANG=C.UTF-8 0B
<missing> 2 days ago /bin/sh -c #(nop) ENV PATH=/usr/java/openjd… 0B
<missing> 2 days ago /bin/sh -c #(nop) ENV JAVA_HOME=/usr/java/o… 0B
<missing> 2 days ago /bin/sh -c set -eux; yum install -y … 144MB
<missing> 2 years ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0B
<missing> 2 years ago /bin/sh -c #(nop) LABEL org.label-schema.sc… 0B
<missing> 2 years ago /bin/sh -c #(nop) ADD file:54b004357379717df… 202MB
- 我這裡已經推送到hub.docker.com上去了,執行以下命令即可下載到本地:
docker pull bolingcavalry/centos7.6-jdk8:0.0.3
CentOS7+JDK8+OpenCV4映象
- 接下來可以整合OpenCV4了,這裡有兩個關鍵點需要注意:
- 受到JavaCV依賴的約束,OpenCV的版本要用<font color="red">4.5.3</font>
- OpenCV編譯的時候要求cmake版本是3.x,因此需要下載cmake對應版本
- 最終,Dockerfile內容如下,基礎映象是前面做好的<font color="blue">bolingcavalry/centos7.6-jdk8:0.0.1</font>,先是安裝一大堆編譯所需的應用,然後下載cmake並安裝,再下載OpenCV-4.5.3版本的原始碼然後編譯,就這麼簡單(但其間的除錯工作還是不少的,不說了,說多了都是淚):
FROM bolingcavalry/centos7.6-jdk8:0.0.1
RUN echo "export LC_ALL=en_US.UTF-8" >> /etc/profile \
&& source /etc/profile
RUN set -eux; \
yum install -y \
make \
gcc \
gcc-c++ \
gtk+-devel \
gimp-devel \
gimp-devel-tools \
gimp-help-browser \
zlib-devel \
libtiff-devel \
libjpeg-devel \
libpng-devel \
gstreamer-devel \
libavc1394-devel \
libraw1394-devel \
libdc1394-devel \
jasper-devel \
jasper-utils \
swig \
python \
libtool \
nasm \
build-essential \
ant \
unzip \
;
RUN set -eux; \
curl -fL -o cmake-3.12.2-Linux-x86_64.tar.gz https://cmake.org/files/v3.12/cmake-3.12.2-Linux-x86_64.tar.gz \
&& tar -zxvf cmake-3.12.2-Linux-x86_64.tar.gz \
&& mv cmake-3.12.2-Linux-x86_64 cmake-3.12.2 \
&& ln -sf /cmake-3.12.2/bin/* /usr/bin; \
curl -fL -o opencv-4.5.3.zip https://codeload.github.com/opencv/opencv/zip/4.5.3; \
unzip opencv-4.5.3.zip; \
rm -rf opencv-4.5.3.zip; \
cd opencv-4.5.3; \
mkdir build; \
cd build; \
cmake -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local ..; \
make; \
make install; \
cmake -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local -DBUILD_TESTS=OFF ..;\
make -j8; \
make install
- 執行命令<font color="blue">docker build -t bolingcavalry/opencv4.5.3:0.0.1 .</font>即可生成映象,如果您有hub.docker.com的賬號,還可以將其推送到中央倉庫,給更多人使用
- 用history命令看看映象內容,詳情如下,倒吸一口涼氣,這麼大的體積,親愛的讀者們會不會打死我...:
will@Mac-mini centos7-jdk8 % docker history bolingcavalry/opencv4.5.3:0.0.1
IMAGE CREATED CREATED BY SIZE COMMENT
d1518ffa4699 5 days ago RUN /bin/sh -c set -eux; curl -fL -o cma… 819MB buildkit.dockerfile.v0
<missing> 5 days ago RUN /bin/sh -c set -eux; yum install -y … 637MB buildkit.dockerfile.v0
<missing> 5 days ago RUN /bin/sh -c echo "export LC_ALL=en_US.UTF… 1.84kB buildkit.dockerfile.v0
<missing> 3 months ago /bin/sh -c set -eux; arch="$(objdump… 209MB
<missing> 3 months ago /bin/sh -c #(nop) ENV LANG=C.UTF-8 0B
<missing> 3 months ago /bin/sh -c #(nop) ENV PATH=/usr/java/openjd… 0B
<missing> 3 months ago /bin/sh -c #(nop) ENV JAVA_HOME=/usr/java/o… 0B
<missing> 3 months ago /bin/sh -c set -eux; yum install -y … 144MB
<missing> 2 years ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0B
<missing> 2 years ago /bin/sh -c #(nop) LABEL org.label-schema.sc… 0B
<missing> 2 years ago /bin/sh -c #(nop) ADD file:54b004357379717df… 202MB
- 我這裡已經推送到hub.docker.com上去了,執行以下命令即可下載到本地:
docker pull bolingcavalry/opencv4.5.3:0.0.1
- 這裡要提醒一下,opencv的編譯是非常耗時的,請確保docker宿主機的效能不要太差,也請您耐心等待編譯過程
- 至此,符合我們們要求的基礎映象<font color="blue">opencv4.5.3:0.0.1</font>已製作完成,有了它,我們們的Java應用所需的jdk和opencv就湊齊了,在開發javacv相關的應用時,以它為基礎映象就無需再為環境和依賴庫操心,終於可以聚焦java開發了
你不孤單,欣宸原創一路相伴
歡迎關注公眾號:程式設計師欣宸
微信搜尋「程式設計師欣宸」,我是欣宸,期待與您一同暢遊Java世界...
https://github.com/zq2599/blog_demos