版權聲明:可以任意轉載,轉載時請標明文章原始出處-ScriptShi
前言
docker處於瞭解並使用的情況,但使用也是在DevOps下使用的,只有一個宏觀的瞭解,因此對docker的各種具體使用也不熟悉,所以決定探索一下,如果內存可以的話,將自己的雲服務器全部docker化。
試驗機介紹
本是在自己的虛擬機裏,但是感覺不是很爽,虛擬機設置個16G內存,8C跑個小docker,對cpu和內存的使用不能真的查看,想在生產環境裏直接看一下效果。
服務器是阿里雲的,今天剛買的一年的學生機,1C 2G 40G-SSD 1M,如下:
安裝的操作系統是centos 7.3
安裝 docker
yum update
curl -fsSL https://get.docker.com/ | sh
service docker start
設置開機啓動:systemctl enable docker
在阿里雲的“開發者平臺”上進行換源,換成國內鏡像,提高速度(腳本中的xxxxx是個人獨有的,由阿里雲生成的)。
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://xxxxxxxxxxxx.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
測試helloworld:docker run hello-world
常見docker命令
列一下docker常用的操作,做個紀念吧。重點會用啓動/停止/刪除、看日誌、進容器裏就可以了。
docker ps -a
查看所有容器docker exec -it xxxxxx /bin/bash
進入容器中並執行一個bash的shell(xxxxx是容器名字或id)docker stop $(docker ps -q)
停用全部運行中的容器docker rm $(docker ps -aq)
刪除全部容器docker stop $(docker ps -q) & docker rm $(docker ps -aq)
一條命令實現停用並刪除容器:docker images | grep -E "(aaa|bbb)" | awk '{print $3}' | uniq | xargs -I {} docker rmi --force {}
刪除包含指定名稱的Docker Image(含有aaa或者bbb的映像文件)docker logs -f xxxxxx
查看容器的日誌(xxxx:id或name,-f : 查看實時日誌;-tail=10 : 查看最後的10條日誌。)docker run
run的參數有:-d, --detach=false 指定容器運行於前臺還是後臺,默認爲false -i, --interactive=false 打開STDIN,用於控制檯交互 -t, --tty=false 分配tty設備,該可以支持終端登錄,默認爲false -u, --user="" 指定容器的用戶 -a, --attach=[] 登錄容器(必須是以docker run -d啓動的容器) -w, --workdir="" 指定容器的工作目錄 -c, --cpu-shares=0 設置容器CPU權重,在CPU共享場景使用 -e, --env=[] 指定環境變量,容器中可以使用該環境變量 -m, --memory="" 指定容器的內存上限 -P, --publish-all=false 指定容器暴露的端口 -p, --publish=[] 指定容器暴露的端口 -h, --hostname="" 指定容器的主機名 -v, --volume=[] 給容器掛載存儲卷,掛載到容器的某個目錄 --cap-add=[] 添加權限,權限清單詳見:http://linux.die.net/man/7/capabilities --cap-drop=[] 刪除權限,權限清單詳見:http://linux.die.net/man/7/capabilities --cidfile="" 運行容器後,在指定文件中寫入容器PID值,一種典型的監控系統用法 --cpuset="" 設置容器可以使用哪些CPU,此參數可以用來容器獨佔CPU --device=[] 添加主機設備給容器,相當於設備直通 --dns=[] 指定容器的dns服務器 --dns-search=[] 指定容器的dns搜索域名,寫入到容器的/etc/resolv.conf文件 --entrypoint="" 覆蓋image的入口點 --env-file=[] 指定環境變量文件,文件格式爲每行一個環境變量 --expose=[] 指定容器暴露的端口,即修改鏡像的暴露端口 --link=[] 指定容器間的關聯,使用其他容器的IP、env等信息 --lxc-conf=[] 指定容器的配置文件,只有在指定--exec-driver=lxc時使用 --name="" 指定容器名字,後續可以通過名字進行容器管理,links特性需要使用名字 --net="bridge" 容器網絡設置: bridge 使用docker daemon指定的網橋 host //容器使用主機的網絡 container:NAME_or_ID >//使用其他容器的網路,共享IP和PORT等網絡資源 none 容器使用自己的網絡(類似--net=bridge),但是不進行配置 --privileged=false 指定容器是否爲特權容器,特權容器擁有所有的capabilities --restart="no" 指定容器停止後的重啓策略: no:容器退出時不重啓 on-failure:容器故障退出(返回值非零)時重啓 always:容器退出時總是重啓 unless-stopped: 除非人工停止,不然自動重啓 --rm=false 指定容器停止後自動刪除容器(不支持以docker run -d啓動的容器) --sig-proxy=true 設置由代理接受並處理信號,但是SIGCHLD、SIGSTOP和SIGKILL不能被代理
docker build -t yyyy xxxx
構建docker鏡像(yyyy:鏡像的名字,xxxxx:dockerFile的所在目錄)
安裝mysql
安裝最新版的mysql:同時設置容器名字,數據卷分離, 暴露端口,設置密碼,後臺啓動,重啓策略,遠程鏡像名字(不帶版本號默認最新版)
docker run --name mysql -v /data/mysql:/var/lib/mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=你的默認密碼 -d --restart=unless-stopped mysql:5.6.35
常用的幾個就是我安裝mysql時候用到的這些。
進入docker容器內部:docker exec -it mysql bash
進入mysql的shell界面:mysql -uroot -p你的mysql用戶密碼
想起來以前安裝mysql好麻煩呀!docker使我感到開心。
在自己電腦上連接遠程服務器,進行遠程連接測試(首先你需要知道這是不安全的和生產環境絕對不允許
的,其次你需要打開防火牆)
如下,測試成功。
SpringBoot 服務的部署
我寫了個只有一個hi的web服務:https://github.com/xjtushilei/jenkins-test.git
並寫了一個簡單的 Dockerfile(下一節簡單講講dockerFile的書寫)
FROM openjdk:8-jdk-alpine
RUN mkdir -p /root/workspace/project
WORKDIR /root/workspace/project
COPY build/libs/*.jar app.jar
#RUN set -ex && ./gradlew build
#RUN cp build/libs/*.jar app.jar
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/root/workspace/project/app.jar"]
其實三行就可以搞定,多寫的主要是爲了練習。
我分別嘗試了在docker裏進行構建和在docker外。(具體採取哪種方式要看DevOps了,自己開發的話還是docker外吧,不然每次從maven中央倉庫拉jar包很難受,即便換爲國內的源;如果在docker內構建的話,可以省略外部代碼編譯這一步,直接從代碼到docker鏡像,但是會延長髮布時間)
我們先把代碼拉下來,
yum install git # 新機器,發現沒裝git,尷尬
git clone https://github.com/xjtushilei/jenkins-test.git
cd jenkins-test
在代碼主目錄下:
- 用gradle編譯打包代碼,會生成可運行的jar
- 構建 docker鏡像
- 運行docker鏡像
yum install java-1.8.0-openjdk java-1.8.0-openjdk-devel # 新機器,發現沒裝jdk,尷尬
./gradlew build
docker build -t hi .
如下所示:構建我自己的docker成功了。
直接非後臺
運行:docker run -p 8080:8080 hi
就看到了如下熟悉的界面:
遠程測試成功:
到現在爲止,我們也學會了如何發佈自己的docker。我這裏推薦使用阿里雲的容器鏡像服務,特別方便!不用自己拉pull代碼,直接用他們的服務檢測git裏代碼的變化,動態更新鏡像。
Dockerfile 大致流程
- Dockerfile的第一條指令一般都是FROM,表示從一個基礎鏡像開始構建
- 執行一條命令對鏡像做出修改
- 提交更新
- 基於本次更新,運行新的容器
- 繼續執行下一條命令
如此反覆執行……
在構建過程中每次生成一層新的鏡像的時候這個鏡像就會被緩存。即使是後面的某個步驟導致構建失敗,再次構建的時候就會從失敗的那層鏡像的前一條指令繼續往下執行。
DockerFile 的書寫
DockerFile分爲四部分組成:基礎鏡像信、維護者信息、鏡像操作指令和容器啓動時執行指令
#第一行必須指令基於的基礎鏡像
From ubutu
#維護者信息
MAINTAINER docker_user [email protected]
#鏡像的操作指令
RUN apt-get update && apt-get install -y ngnix
RUN echo "\ndaemon off;">>/etc/ngnix/nignix.conf
#容器啓動時執行指令
CMD /usr/sbin/ngnix
下面講一下DockerFile常見的指令
FROM
格式爲FROM或FROM:。
第一條指令必須爲FROM指令。並且,如果在同一個Dockerfile中創建多個鏡像時,可以使用多個FROM指令(高版本docker建議搭配as使用)。
MAINTAINER
格式爲MAINTAINER,指定維護者信息。
RUN
格式爲RUN
或RUN["executable", "param1", "param2"]
。
前者將在shell終端中運行命令,即/bin/sh -c;後者則使用exec執行。指定使用其它終端可以通過第二種方式實現,例如RUN ["/bin/bash", "-c", "echo hello"]
。
每條RUN指令將在當前鏡像基礎上執行指定命令,並提交爲新的鏡像。當命令較長時可以使用\來換行。
CMD
支持三種格式
CMD ["executable","param1","param2"]
使用exec執行,推薦方式;CMD command param1 param2
在/bin/sh中執行,提供給需要交互的應用;CMD ["param1","param2"]
提供給ENTRYPOINT的默認參數;
指定啓動容器時執行的命令,每個Dockerfile只能有一條CMD命令。如果指定了多條命令,只有最後一條會被執行。
如果用戶啓動容器時候指定了運行的命令,則會覆蓋掉CMD指定的命令。
EXPOSE
格式爲EXPOSE [...]
。
告訴Docker服務端容器暴露的端口號,供互聯繫統使用。
這裏僅僅是告訴,如果想給宿主機調用的話,需要run的時候-p 進行端口轉發。
ENV
格式爲ENV
。 指定一個環境變量,會被後續RUN指令使用,並在容器運行時保持。
例如
ENV PG_MAJOR 9.3
ENV PG_VERSION 9.3.4
RUN curl -SL http://example.com/postgres-$PG_VERSION.tar.xz | tar -xJC /usr/src/postgress && …
ENV PATH /usr/local/postgres-$PG_MAJOR/bin:$PATH
ADD
格式爲ADD
。
該命令將複製指定的到容器中的。 其中可以是Dockerfile所在目錄的一個相對路徑;也可以是一個URL;還可以是一個tar文件(自動解壓爲目錄)。
COPY
格式爲COPY。
複製本地主機的(爲Dockerfile所在目錄的相對路徑)到容器中的。
當使用本地目錄爲源目錄時,推薦使用COPY。這是和ADD的主要區別。
ENTRYPOINT
兩種格式:
ENTRYPOINT ["executable", "param1", "param2"]
ENTRYPOINT command param1 param2
(shell中執行)
配置容器啓動後執行的命令,並且不可被docker run提供的參數覆蓋。
每個Dockerfile中只能有一個ENTRYPOINT,當指定多個時,只有最後一個起效。
VOLUME
格式爲VOLUME ["/data"]
。
創建一個可以從本地主機或其他容器掛載的掛載點,一般用來存放數據庫和需要保持的數據等。
USER
格式爲USER daemon。
指定運行容器時的用戶名或UID,後續的RUN也會使用指定用戶。
當服務不需要管理員權限時,可以通過該命令指定運行用戶。並且可以在之前創建所需要的用戶,例如:RUN groupadd -r postgres && useradd -r -g postgres postgres。要臨時獲取管理員權限可以使用gosu,而不推薦sudo。
WORKDIR
格式爲WORKDIR /path/to/workdir。
爲後續的RUN、CMD、ENTRYPOINT指令配置工作目錄。
可以使用多個WORKDIR指令,後續命令如果參數是相對路徑,則會基於之前命令指定的路徑。例如
WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd
則最終路徑爲/a/b/c。
docker的其他注意事項
和
都必須是目錄- “必須是容器中的絕對路徑
- 路徑如果不存在,執行完成之後,docker 會給宿主機創建該目錄;
`可以使用相對路徑,但是相對的並不是當前的工作目錄,而是
/var/lib/docker/volumes/` - 如果只有一個路徑,比如
docker run -it -v
,這種情況叫做匿名掛載,表示的是 container 中的位置,宿主機會在`/var/lib/docker/volumes/`下隨機創建一個目錄與 container 中的
對應 不管以何種方式 mount,容器銷燬之後,由 -v 在宿主機上創建的目錄不會銷燬
<host-path>
和<container-path>
都必須是目錄<container-path>
必須是容器中的絕對路徑- 路徑如果不存在,執行完成之後,docker 會給宿主機創建該目錄;
<host-path>
可以使用相對路徑,但是相對的並不是當前的工作目錄,而是/var/lib/docker/volumes/
- 如果只有一個路徑,比如
docker run -it -v <path> <image>
,這種情況叫做匿名掛載,<image>
表示的是 container 中的位置,宿主機會在/var/lib/docker/volumes/
下隨機創建一個目錄與 container 中的<path>
對應 - 不管以何種方式 mount,容器銷燬之後,由 -v 在宿主機上創建的目錄不會銷燬