自己有一個簡單的springboot web后端項目,每次部署的時候都是上傳到服務器,然后nohup java -jar 運行打包的jar包。這樣每次運行都要輸命令,關閉時還得找到進程id手動kill掉,覺得太煩了,干脆做成docker鏡像。
編寫Dockerfile
首先將需要的文件放在一個文件夾下。這里就只需要一個項目的jar包就行了,但如果想把其他用到的軟件也打包進鏡像,最好也要放進來。
在文件夾下創建Dockerfile文件,開始編寫docker容器構建腳本。

#依賴java8
#openjdk:8 526M
#FROM openjdk:8
#tomcat:8-jre8 240M
FROM tomcat:8-jre8
#創建者
MAINTAINER liftsail
#暴露8848
EXPOSE 8848
#不確定jar名字可以寫*.jar 即為所以
ADD ddisk-1.0.0.jar /app.jar
#掛載目錄
VOLUME /tmp
#容器已啟動 默認運行命令 java -jar app.jar
#生產環境啟動 可以寫#容器已啟動 默認運行命令 java -jar app.jar
#ENTRYPOINT ["java","-jar","/app.jar","--spring.profiles.active=prod"]
#解決OOM問題 指定內存初始128M 最大300M ENTRYPOINT ["java","-jar","-Xms128m","-Xmx300m","/app.jar","--spring.profiles.active=prod"]
ENTRYPOINT ["java","-jar","/app.jar"]
FROM openjdk:15,表示本鏡像的基礎鏡像是openjdk,版本是15,畢竟要用java命令運行jar包的。docker會從dockerhub拉取對應的鏡像,服務器不需要有。
MAINTAINER liftsail,表示鏡像的編寫者。
ADD test.jar app.jar,表示將test.jar,也就是項目jar包,拷貝進鏡像,並命名為app.jar。如果不拷貝,鏡像就沒jar包可運行了。
EXPOSE 8080,表示鏡像將對外暴露8080端口,也就是編寫項目時的運行端口。
VOLUME /file,表示將鏡像的/file文件夾聲明為匿名卷。這樣做是因為,項目會讀寫文件系統的/file文件夾,如果不聲明,那么項目運行后只會對鏡像內的虛擬目錄/file讀寫,而不會對主機的目錄讀寫,等關閉容器后,寫的內容就沒了。所以,聲明匿名卷是為了將寫操作持久化。僅僅在dockerfile里聲明還不夠,在運行容器時還需要設置匿名卷對應的主機目錄,這點我們下面會談到。
ENTRYPOINT java -jar app.jar,表示容器運行后執行的命令。這里就只需要運行jar包就行了。
構建鏡像
編寫了Dockerfile,就可以構建鏡像了。
docker build -t test_app:0.1 .
test_app是鏡像的名字,-t代表給鏡像打的標簽,后面的:0.1意思就是這個鏡像版本是0.1。如果不打標簽,鏡像的標簽會自動設為latest。
最后的一個'.'代表Dockerfile所在位置,因為就在當前目錄下,所以直接是一個'.'就行了。
docker會自動拉取openjdk。一會出現“Successfully built 7717b14bfe0a”,說明構建成功。
運行容器
接下來運行容器。
docker run -d --name test_app -v /home/file:/file --net=host -p 8080:8080 test_app:0.1
docker run -d -p 8848:8848 --name diskstore1 --restart=always 612d04579214
-d指在后台運行。
--name為容器起名。
-v指定容器匿名卷掛載的目錄。這里/home/file:/file代表將主機的/home/file對應到容器的/file,也就是說,容器對/file目錄的讀寫也就是對主機的/home/file讀寫。
--net=host指定容器的網絡模式。host是最簡單的模式,容器和主機共用一個網絡,會互相占用端口。由於項目簡單,我就沒有再研究其他模式了,想研究的話可以看看官網教程。
-p 8080:8080指定端口映射。這里簡單的將主機的8080端口映射到容器的8080端口。如果想要多個web程序運行在同一主機,不需要改代碼里的運行端口,直接將主機的不同端口映射到容器的8080即可。
最后是容器使用的鏡像,也就是剛剛構建好的test_app:0.1:也可以是容器的id。
進入容器內部 41c614982e46 為容器ID
docker exec -it 41c614982e46 bash
就這樣,容器成功運行了。只要docker start/stop就能控制程序運行,部署新版本時,也只要將jar包再上傳到目錄下,重新構建即可。
DOCKER容器常用啟動參數詳解
docker run [option] 鏡像名 [向啟動容器中傳入的命令]
#例如:docker運行mysql8.0.30並設置密碼為root
docker run -p 3306:3306 --name mysql -e MYSQL_ROOT_PASSWORD=root --restart=always --privileged=true -d mysql:8.0.30
#--restart=always 參數能夠使我們在重啟docker時,自動啟動相關容器。
#Docker容器的重啟策略如下:
#no,默認策略,在容器退出時不重啟容器
#on-failure,在容器非正常退出時(退出狀態非0),才會重啟容器
#on-failure:3,在容器非正常退出時重啟容器,最多重啟3次
#always,在容器退出時總是重啟容器
#unless-stopped,在容器退出時總是重啟容器,但是不考慮在Docker守護進程啟動時就已經停止了的容器
#--privileged=true 使用該參數,container內的root擁有真正的root權限。
#不使用該參數,container內的root只是外部的一個普通用戶權限。
#大約在0.6版,privileged被引入docker
#privileged啟動的容器,可以看到很多host上的設備,並且可以執行mount。
#甚至允許你在docker容器中啟動docker容器。
i 表示以“交互模式”運行容器
-t 表示容器啟動后會進入其命令行。加入這兩個參數后,容器創建就能登錄進去。即 分配一個偽終端。
–name 為創建的容器命名
-v 表示目錄映射關系(前者是宿主機目錄,后者是映射到宿主機上的目錄,即 宿主機目錄:容器中目錄),可以使 用多個-v 做多個目錄或文件映射。注意:最好做目錄映射,在宿主機上做修改,然后 共享到容器上。
-d 在run后面加上-d參數,則會創建一個守護式容器在后台運行(這樣創建容器后不 會自動登錄容器,如果只加-i -t 兩個參數,創建后就會自動進去容器)。
-p 表示端口映射,前者是宿主機端口,后者是容器內的映射端口。可以使用多個-p 做多個端口映射
-e 為容器設置環境變量
–network=host 表示將主機的網絡環境映射到容器中,容器的網絡與主機相同
linux centos7系列關閉防火牆但是端口依然無法訪問
centos7.3系統,已經關閉firewalld,但是除了22端口,其余端口無法被外界訪問,本地訪問正常,解決步驟:
1、先開啟firewalld:systemctl start firewalld
2、放通端口:firewall-cmd --zone=public --add-port=8080/tcp --permanent
3、重新加載配置文件:firewall-cmd --reload
此時測試,端口已經能夠訪問了,如果不需要firewall,可以再關閉,已放通端口不受影響(為什么一開始我不放通端口直接關閉firewall不行?這點有了解的大神幫忙解答下)
注:firewall依賴本機python版本,如果自己升級了python版本,需要修改firewall配置文件(實際版本號以本機實際為准,我的為2.7):
1、vim /usr/bin/firewall-cmd, 將#!/usr/bin/python -Es 改為 #!/usr/bin/python2.7 -Es
2、vim /usr/sbin/firewalld, 將#!/usr/bin/python -Es 改為 #!/usr/bin/python2.7 -Es

