更多精彩內容請關注微信公衆號:新猿技術生態圈html
定製docker鏡像的方式有兩種:java
手動修改容器內容,導出新的鏡像。python
基於dockerfile自行編寫指令,基於指令流程建立鏡像。mysql
鏡像是多層存儲,每一層都是在前一層的基礎上進行修改;
容器也是多層存儲,以鏡像爲基礎層,在其基礎上加一層做爲容器運行時的存儲層。
剛纔說了,建立鏡像的兩個方法:linux
手動修改容器內容,而後dokcer commit提交容器爲新的鏡像nginx
經過在dockerfile中定義一系列的命令和參數構建成的腳本,而後這些命令應用於基礎鏡像,依次添加層,最終生成一個新的鏡像。極大的簡化了部署工做。web
Dockerfile主要組成部分
基礎鏡像信息 FROM centos:7.9 製做鏡像操做指令 RUN yum install -y nginx 容器啓動時執行指令 CMD ["/bin/bash"]
宿主機直接部署軟件流程與Dockerfile部署軟件流程對比
需求 : 安裝一個mysql,並啓動。面試
虛擬機部署形式:sql
1. 開啓vmware 2. 運行某一個虛擬即,centos7 3. centos7安裝mysql yum install mysql-server 4. 經過腳本或者命令,啓動mysql便可 部署緩慢,且修改了宿主機的環境,刪除較爲麻煩,佔用宿主機的一個3306端口容器的部署形式:docker
1. 開始vmware 2. 運行虛擬機centos7(宿主機) 3. 安裝docker容器軟件 4. 獲取mysql鏡像便可,docker pull mysql:tag(你沒法自由控制,該mysql的基礎鏡像時什麼發行版本,你獲取的鏡像,是別人定製好的,你下載使用的默認時Debian發行版,你但願獲得一個基於centos7.9的發行版本,運行mysql) 5. 直接運行該鏡像,經過端口映射,運行mysql 6. 訪問宿主機對的一個映射端口,訪問到容器內的mysql想自定義鏡像,就得本身寫腳本,也就是dockerfile了
FROM 指定基礎鏡像 MAINTAINER 指定維護者信息,能夠沒有 RUN 你想讓它幹啥(在命令前面加上RUN便可) ADD 添加宿主機的文件到容器內,還多了一個自動解壓的功能 # RUN tar -Zxf /opt/xx.tgz # 報錯!該tgz文件不存在! ! COPY 做用和ADD是同樣的,都是拷貝宿主機的文件到容器內, COPY就是僅僅拷貝 WORKDIR 至關於cd命令,設置當前工做目錄 VOLUME 設置目錄映射,掛載主機目錄 EXPOSE 指定對外的端口,在容器內暴露一個端口,端口 EXPORT 80 CMD 指定容器啓動後的要乾的事情 ENTRYPOINT 做用和CMD同樣,都是在指定容器啓動程序以及參數。 # 當指定了ENTRYPOINT以後,CMD指令的語義就有了變化,而是把CMD的內容看成參數傳遞給ENTRYPOINT指令。 ARG 設置環境變量 # ARG只是用於構建鏡像須要設置的變量,容器運行時就消失了 ENV 和ARG同樣,都是設置環境變量 # 區別在於ENV不管是在鏡像構建時,仍是容器運行,該變量均可以使用 USER 用於改變環境,用於切換用戶
需求:經過dockerfile,構建nginx鏡像,且運行容器後,生成的頁面是"辣辣小姐姐"。
1. 建立Dockerfile,注意文件名,必須是這個 [root@docker01 ~]# mkdir /learn_docker [root@docker01 ~]# cd /learn_docker/ [root@docker01 learn_docker]# vim Dockerfile FROM nginx RUN echo "<meta charset=utf-8>辣辣小姐姐" > /usr/share/nginx/html/index.html 2. 構建Dockerfile [root@docker01 learn_docker]# docker build . 3. 修改鏡像名字 [root@docker01 learn_docker]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE <none> <none> 950549357c1f 18 seconds ago 133MB nginx latest 08b152afcfae 6 days ago 133MB [root@docker01 learn_docker]# docker tag 950549357c1f my_nginx 4. 運行該鏡像 docker run -d -p 80:80 my_nginx 5. 查看宿主機的80端口 http://192.168.15.80/ # 辣辣小姐姐
更多精彩內容請關注微信公衆號:新猿技術生態圈
COPY
copy指令從宿主機複製文件或者目錄到新的一層鏡像內 如: copy nana.py /opt 支持多個文件,以及通配符形式的複製,語法要知足Golang的filepath.Match copy na* /tmp/cc?.txt /opt COPY指令可以保留源文件的元數據,訪問時間等等,這點很重要
ADD
特性和COPY基本一致,不過多了些功能 1. 源文件是一個URL,此時dockcer引擎會下載該連接,放入目標路徑,且權限自動設爲600。若這不是指望結果,還得增長一層RUN指令進行調整 # ADD nana.tgz /home # RUN xxx修改命令 2. 源文件是一個URL,且是一個壓縮包,不會自動解壓,也得單獨用RUN指令解壓 3. 源文件是一個壓縮文件,且是gzip,bzip,xz,tar狀況,ADD指令會自動解壓壓縮該文件到沒有文件
CMD
用法,注意是雙引號 # CMD在容器內運行某個命令,啓動程序 # 該鏡像在運行容器實例的時候,執行的具體參數是什麼 CMD["參數1","參數2"] 在指定了entrypoint指令後,用CMD指定具體的參數 dokcer不是虛擬機,容器就是一個進程,既然是進程,那麼程序在啓動的時候須要指定些運行參數,這就是CMD指令做用 例如centos鏡像默認的CMD是/bin/bash,直接docker run -it centos會直接進入bash解釋器。 也能夠啓動容器時候,指定參數: docker run -it centos cat /etc/os-release CMD ["/bin/bash"] # 該容器運行時,執行的命令 # 等同於命令行的直接操做:docker run -it centos cat /etc/os-release CMD ["cat","/etc/os-release"]
容器內運行程序
這裏要注意的是,docker不是虛擬機的概念,虛擬機的程序運行,基本上都是在後臺運行,利用systemctl運行,可是容器內沒有後臺進程的概念,必須在前臺運行。
容器就是爲了主進程而存在的,主進程若是退出了,容器也就失去意義,自動退出。
例如一個經典的問題: # 這樣的寫法是錯誤的,容器會當即退出 CMD systemctl start nginx 由於systemctl start nginx是以守護進程(默認在後臺運行)的形式啓動nginx,且CMD命令會轉化爲 CMD ["sh","-c","systemctl start nginx" ] 這樣的命令主進程是sh解釋器,執行完畢後當即結束了,所以容器也就退出了。 # 至關於nginx -g daemon off 所以正確的作法應該是 CMD ["nginx","-g","daemon off;"]
把宿主機安裝,啓動nginx的理念放入到dockerfile中 1. RUN yum install nginx 2. RUN 配置文件修改 sed # RUN systemctl start nginx 容器內的程序必須在前臺運行,容器時啓動不了的 3. 正確的寫法應該時CMD ["nginx","-g","daemon off;"]
ENTRYPOINT
dokcer面試題:
ENTRYPOINT和CMD的區別以及用法! ! !ENTRYPOINT做用和CMD同樣,都是在指定容器啓動程序以及參數。 當指定了ENTRYPOINT以後,CMD指令的語義就有了變化,而是把CMD的內容看成參數傳遞給ENTRYPOINT指令。
ENTRYPOINT和CMD的實際用法
實際用法: 1. 準備一個Dokcerfile [root@docker01 ~]# cd /learn_docker/ [root@docker01 learn_docker]# > Dockerfile [root@docker01 learn_docker]# vim Dockerfile FROM centos:7.8.2003 RUN rpm --rebuilddb && yum install epel-release -y RUN rpm --rebuilddb && yum install curl -y CMD ["curl","-s","ip.sb"] # 用法以下 dokcer run my_centos curl -s ip.sb # curl -s ip.sb獲取本機的公網ip地址 2. 構建鏡像 [root@docker01 learn_docker]# docker build . Sending build context to Docker daemon 2.048kB Step 1/4 : FROM centos:7.8.2003 ---> afb6fca791e0 Step 2/4 : RUN rpm --rebuilddb && yum install epel-release -y ---> Using cache ---> 81b4e83fb0a5 Step 3/4 : RUN rpm --rebuilddb && yum install curl -y ---> Using cache ---> bd0074c78b6c Step 4/4 : CMD ["curl","-s","ip.sb"] ---> Running in 295418f71093 Removing intermediate container 295418f71093 ---> c920b743282a Successfully built c920b743282a 3. 查看結果(出現Successfully表明鏡像構建完成) Step 4/4 : CMD ["curl","-s","ip.sb"] ---> Running in 295418f71093 Removing intermediate container 295418f71093 ---> c920b743282a Successfully built c920b743282a 4. 檢查鏡像 [root@docker01 learn_docker]# docker tag c920b743282a centos_curl [root@docker01 learn_docker]# docker images | grep curl centos_curl latest c920b743282a 3 minutes ago 471MB 5. 運行鏡像,生成容器記錄,沒有前臺運行,所以當即掛了 [root@docker01 learn_docker]# docker run centos_curl 139.227.102.189 6. 上述運行正確,可是我想再傳入一個參數,該怎麼辦 # 發現是沒法直接傳入參數的,該形式是覆蓋鏡像中的cmd # 就比如把docker鏡像,看成一個環境,去執行後面的命令 [root@docker01 learn_docker]# docker run centos_curl pwd / [root@docker01 learn_docker]# [root@docker01 learn_docker]# docker run centos_curl -I docker: Error response from daemon: OCI runtime create failed: container_linux.go:380: starting container process caused: exec: "-I": executable file not found in $PATH: unknown. 7. 想要正確的給容器傳入一個參數該怎麼辦 但願容器內可以正確完整的運做該命令的執行結果 [root@docker01 learn_docker]# curl -s ip.sb -I # 獲取http報頭信息 HTTP/1.1 200 OK Date: Wed, 28 Jul 2021 15:16:18 GMT ... 8. 解決辦法 方式一:給容器傳入新的完整的命令,讓後面的命令覆蓋鏡像中的cmd # 這是投機取巧的辦法,不合適 [root@docker01 learn_docker]# docker run centos_curl curl -s ip.sb -I HTTP/1.1 200 OK Date: Wed, 28 Jul 2021 15:18:05 GMT Content-Type: text/plain 9. 正確的解決辦法 [root@docker01 learn_docker]# vim Dockerfile FROM centos:7.8.2003 RUN rpm --rebuilddb && yum install epel-release -y RUN rpm --rebuilddb && yum install curl -y ENTRYPOINT ["curl","-s","ip.sb"] 10. 從新構建鏡像 # 從新構建鏡像速度特別快,而且咱們發現鏡像的前三個Step的IMAGE ID是一致的,說明前三個的IMAGE ID是直接從緩存中拿的。 # 只有Step 4/4的IMAGE ID發生了變化(Dockerfile文件的第四步是更改過的,是從新構建的鏡像層),所以更加驗證了咱們以前所提到的鏡像是分層構建的。 [root@docker01 learn_docker]# docker build . Sending build context to Docker daemon 2.048kB Step 1/4 : FROM centos:7.8.2003 ---> afb6fca791e0 Step 2/4 : RUN rpm --rebuilddb && yum install epel-release -y ---> Using cache ---> 81b4e83fb0a5 Step 3/4 : RUN rpm --rebuilddb && yum install curl -y ---> Using cache ---> bd0074c78b6c Step 4/4 : ENTRYPOINT ["curl","-s","ip.sb"] ---> Running in df106e04d533 Removing intermediate container df106e04d533 ---> e9479067148c Successfully built e9479067148c 11. 從新運行該鏡像,看結果,以及傳入新的參數 [root@docker01 learn_docker]# docker tag e9479067148c centos_curl_new # 此時發現,傳入的CMD指令,看成了ENTRYPOINT的參數 # 其實容器內,執行的完命令是: curl -s ip.sb -I [root@docker01 learn_docker]# docker run centos_curl_new -I HTTP/1.1 200 OK Date: Wed, 28 Jul 2021 15:24:58 GMT ...
ARG和ENV指令
設置環境變量
dockerfile腳本,shell腳本 ENV NAME="nana" ENV AGE=18 ENV MYSQL_VERSION=5.6 後續全部的操做,經過$NAMME就能夠直接獲取變量值使用了,維護dockerfile更加方便 ARG和ENV同樣,都是設置環境變量 ENV不管是在鏡像構建時,仍是容器運行,該變量均可以使用 ARG只是用於構建鏡像須要設置的變量,容器運行時就消失了
VOLUME
容器在運行時,應該保證在存儲層不寫入任何數據,運行在容器內產生的數據,咱們推薦是掛載,寫入到宿主機上,進行維護。
# mount /mnt VOLUME /data # 將容器內的/data文件夾,在容器運行時,該目錄自動掛載爲匿名卷,任何向該目錄中寫入數據的操做,都不會被容器記錄,保證的容器存儲無狀態理念。 # Dockerfile [root@docker01 ~]# cd /learn_docker/ [root@docker01 learn_docker]# > Dockerfile [root@docker01 learn_docker]# vim Dockerfile FROM centos MAINTAINER nana VOLUME ["/data1","/data2"] # 該容器運行的時候,這兩個目錄自動和宿主機的目錄作好映射關係 docker build . # 運行該鏡像 docker run 86b4dceba89a # 查看生成的容器信息 [root@docker01 nana]# docker ps -a | head -2 CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 84014622b3a4 86b4dceba89a "/bin/bash" 2 minutes ago Exited (0) 2 minutes ago sharp_noether # dokcer inspect命令查看 [root@docker01 learn_docker]# docker inspect 86b4dceba89a "Volumes": { "/data1": {}, "/data2": {} }, 1. 容器數據掛載的方式,經過dockerfile,指定VOLUME目錄 2. 經過docker run -v參數,直接設置須要映射掛載的目錄
EXPOSE
指定容器運行時對外提供的端口服務。
幫助使用該鏡像的人,快速理解該容器的一個端口業務 docker port 容器 dokcer run -p 宿主機端口:容器端口 docker run -P # 做用是隨機 宿主機端口:容器內端口
WORKDIR
用於在dockerfile中,目錄的切換,更改工做目錄
WORKDIR /opt
USER
用於改變環境,用於切換用戶
USER root USER nana
傳統方式建立一個網站站點
- nginx,修改首頁內容,html網站就跑起來了。web server,提供web服務,提供代理轉發,提供網關,限流等等。。。
- web framework。web框架,通常由開發,經過某個開發語言,基於某個web框架,本身去開發一個web站點,python,django框架。
使用Dockerfile建立一個網站站點
- 用python語言,基於flask web框架,開發一個本身的網站,寫一個後端的網站代碼
- 開發dockerfile,部署該代碼,生成鏡像
- 其餘人基於該鏡像,docker run就能夠在電腦跑起來你這個網站
使用docker的優點
好比安裝一個etcd、naco,都是一些比較複雜的軟件。
須要依賴於go語言環境,好比須要依賴於java環境,在本身的機器安裝好對應的開發環境,以及對應的版本,以及各類依賴。。。
tomcat 依賴於jdk環境 當你有了docker, docker pull tomcat # 這些主流的鏡像均可以直接找到,而且該鏡像中,就已經打包好了java環境 docker run tomcat xxx ... # 直接能夠訪問tomcat了
1. 在宿主機下,準備一個目錄,準備好dockerfile,代碼文件 # 寫一個flask的python代碼 # 建立代碼文件 [root@docker01 ~]# cd /learn_docker/ [root@docker01 ~]# vim nana_flask.py #coding:utf8 from flask import Flask app=Flask(__name__) # @app.route(裝飾器),網站的route,指的是url地址後面的文件路徑 @app.route("/nana") def nana(): return "From Docker,nana是隻臭豬豬!!!" if __name__=="__main__": app.run(host="0.0.0.0",port=8080) 2. 編寫Dockerfile [root@docker01 learn_docker]# vim Dockerfile FROM centos:7.8.2003 RUN curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo; RUN curl -o /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo; RUN yum makecache fast; RUN yum install python3-devel python3-pip -y RUN pip3 install -i https://pypi.douban.com/simple flask COPY nana_flask.py /opt WORKDIR /opt EXPOSE 8080 CMD ["python3","nana_flask.py"] 3. 構建鏡像 # --no-cache不是使用以前舊的緩存,從新構建鏡像 [root@docker01 learn_docker]# docker build --no-cache -t "nana_flask" . ... Successfully built 9e731f439e41 Successfully tagged nana_flask:latest 4. 查看構建好的鏡像 [root@docker01 learn_docker]# docker images | head -2 REPOSITORY TAG IMAGE ID CREATED SIZE nana_flask latest 9e731f439e41 3 minutes ago 649MB 5. 運行鏡像,生成容器 [root@docker01 learn_docker]# docker run -d --name nana_flask_web01 -p 90:8080 nana_flask d9f2f83d16bdd0364473d6e4043c433cbd8e3286e87ecbf93fb3fd5e08ac8002 [root@docker01 learn_docker]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES d9f2f83d16bd nana_flask "python3 nana_flask.…" 2 minutes ago Up 2 minutes 0.0.0.0:90->8080/tcp, :::90->8080/tcp nana_flask_web01 6. 訪問宿主主機,查看容器內的flask web網站 瀏覽器輸入: http://192.168.15.80:90/nana # From Docker,nana是隻臭豬豬!!!
如何修改容器內的網站的內容
方法一:修改宿主機的代碼,以及dockerfile,從新構建鏡像
[root@docker01 ~]# vim nana_flask.py ... def nana(): return "From Docker,nana是隻臭豬豬!!!" # 修改return值,從新生成鏡像 ...
方法二:你能夠經入到已經運行的容器內,修改代碼,重啓容器便可
1. 進入容器內部 [root@docker01 learn_docker]# docker exec -it d9f2f83d16bd bash [root@d9f2f83d16bd opt]# ls nana_flask.py 2. 修改容器內的代碼 [root@d9f2f83d16bd opt]# vi nana_flask.py #coding:utf8 from flask import Flask app=Flask(__name__) # @app.route(裝飾器),網站的route,指的是url地址後面的文件路徑 @app.route("/nana") def nana(): return "From Docker,nana是隻臭豬豬!!!ABC!!!" if __name__=="__main__": app.run(host="0.0.0.0",port=8080) 3. 退出容器並重啓容器 [root@d9f2f83d16bd opt]# exit exit [root@docker01 learn_docker]# docker restart d9f2f83d16bd d9f2f83d16bd [root@docker01 learn_docker]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES d9f2f83d16bd nana_flask "python3 nana_flask.…" 4 minutes ago Up About a minute 0.0.0.0:90->8080/tcp, :::90->8080/tcp nana_flask_web01 4. 訪問宿主主機,查看容器內的flask web網站 瀏覽器輸入: http://192.168.15.80:90/nana # From Docker,nana是隻臭豬豬!!!ABC!!!
更多精彩內容請關注微信公衆號:新猿技術生態圈
Docker容器文件系統
容器是docker的一個核心概念,容器使用一個或者一組應用,他的運行狀態以下:
docker利用容器運行應用程序
容器是鏡像的運行實例,能夠被run、start、stop、rm
每一個容器都是互相隔離,保證平臺暗轉
容器能夠看做是一個簡易版Linux環境(沒有Linux內核,有root權限、進程、用戶空間、網絡)
鏡像是隻讀的,容器在啓動的時候建立一層可寫層
dokcerfile面向開發,docker image(鏡像)做爲交付標準,docker container(容器)涉及部署和運維,三者合起來完成docker體系。FROM ubuntu:14.04 選擇基礎鏡像 ADD run.sh 添加文件鏡像,這一層鏡像只有一個內容,就是這個文件 VOLUME /data 設定存儲目錄,並未添加文件,只是更新了鏡像的json文件,便於啓動時候讀取該層信息 CMD ["./run.sh"] 更新json文件,設定程序入口
docker容器管理總結
# 運行鏡像,且進入容器內 [root@docker01 ~]# docker run -it ubuntu bash root@7478064e9fff:/# # 容器運行web程序 # 注意端口使用,數字大一點,建議8000之後開始使用 # --restart=always容器在後臺掛掉後,默認重啓容器 [root@docker01 ~]# docker run --name my_nginx -d --restart=always -p 8000:80 nginx 79d7fcfdc60f2c40e6d92790be6ad6f3bf9db49fda0e46cadb196be6677b4f73 [root@docker01 ~]# docker ps | head -2 CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 79d7fcfdc60f nginx "/docker-entrypoint.…" 40 seconds ago Up 39 seconds 0.0.0.0:8000->80/tcp, :::8000->80/tcp my_nginx 瀏覽器訪問:http://192.168.15.80:8000/ ==> 能夠訪問到nginx # 查看容器內日誌,實時刷新 docker logs -f # 查看運行時,以及掛掉的容器記錄 docker ps 在運行的容器 dokcer ps -a 掛掉以及活着的容器 # 中止啓動 docker start docker stop # 進入容器內 docker exec -it 容器id bash # 刪除容器 docker rm 容器id docker rm `docker ps -qa` # 強制殺死並刪除容器 docker rm -f 容器id # 查看容器進程資源信息 docker top 容器id # 查看容器內資源 docker stats 容器id # 查看容器具體信息 docker inspect 容器id # 獲取容器內的ip地址,容器的格式化參數 docker inspect --format '{{ .NetworkSettings.IPAddress }}' 容器id
dokcer run啓動容器的時候,dokcer後臺操做流程是
- 檢查本地是否有該鏡像,沒有就下載
- 利用鏡像建立且啓動一個容器
- 分配容器文件系統,在只讀的鏡像層掛載讀寫層
- 宿主機的網橋接口會分配一個虛擬接口到容器中
- 容器得到地址池的ip地址
- 執行用戶指定的程序
- 若程序裏沒有進程在運行,容器執行完畢後當即終止
更多精彩內容請關注微信公衆號:新猿技術生態圈
更多精彩內容請關注微信公衆號:新猿技術生態圈
更多精彩內容請關注微信公衆號:新猿技術生態圈