發佈時間:2020年3月25日
發佈者:progorhtml
docker是一種容器技術,爲何如今容器技術那麼火?mysql
容器可以打包應用和隔離運行環境,這是出發點。linux
容器打包應用快速而高效。git
容器的資源使用效率比VM高。在理論上,他確定要比本來無容器下更消耗資源,但他換來的是與環境的隔離,避免了不一樣環境的問題。而他與另外一種環境隔離技術--虛擬機技術相比又更加節省資源,由於虛擬機是虛擬出一臺完整的機器。容器使用宿主機硬件,不須要像虛擬機同樣虛擬硬件。docker使用宿主機的操做系統內核,不須要像虛擬機那樣從新建立一個內核(建立內核消耗時間較多)。相應的,容器的啓動速度也要快於虛擬機。github
容器能夠部署在各類平臺,只要這個平臺可以安裝docker,而後就能夠在docker上部署容器。web
容器的部署很快。若是你使用了一臺物理機來部署你的應用,若是某天你的物理機掛了,那麼你須要在另一臺機上安裝各類環境,而後再部署應用。但容器的話就像一套環境的模板,部署很快。redis
【最重要的一點】容器的打包是把環境一塊兒打包的,就保證了每一個應用的運行環境都會是如出一轍的。一次打包,多地運行。不少時候,BUG都是因爲環境不一樣致使的,相同的環境能夠避免一些BUG的產生。sql
現實使用意義:
docker因爲其快速部署和一次構建屢次部署的特性,使得根據服務器的壓力動態快速部署服務端成爲可能,比人工部署服務端快速得多。docker
1.卸載可能存在的舊版的docker:shell
yum remove docker \ docker-client \ docker-client-latest \ docker-common \ docker-latest \ docker-latest-logrotate \ docker-logrotate \ docker-engine
2.安裝所需的軟件包:
yum install -y yum-utils \ device-mapper-persistent-data \ lvm2
3.設置下載docker的yum庫
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
4.安裝最新版docker-ce
yum install -y docker-ce
5.啓動docker
systemctl daemon-reload && systemctl start docker
6.查看docker信息,若是打印成功,那麼就是安裝成功了:
docker info
docker建立一個容器須要對應的鏡像,而鏡像一般都是從docker hub上下載的,docker hub的功能有點像github,都是一種倉庫,docker hub是存儲鏡像的倉庫。
可是docker hub是一個國外的網站,他的訪問速度不太行,github的不穩定你們應該也深有感覺了。因此咱們要修改docker 拉取鏡像的鏡像源,讓他從國內的一些鏡像網站來拉取鏡像,這些國內的鏡像都會依靠本身的穩定網絡不斷同步docker hub。
編輯/etc/docker/daemon.json
文件,把裏面registry-mirrors
的值改爲下面的:【還能夠自行增長阿里雲的源】
vi /etc/docker/daemon.json
{ "registry-mirrors": [ "http://hub-mirror.c.163.com", "https://registry.docker-cn.com" ] }
阿里的鏡像源仍是比較穩定的,能夠進入阿里雲搜索容器鏡像服務,而後按照下圖來找到加速地址:
這是一個使用docker來建立一個包含了mysql的容器,咱們藉助這個例子來體驗docker建立應用容器的快速。
1.安裝以後,運行systemctl start docker
啓動docker,而後執行如下命令:
docker pull mysql:5.7
當這樣顯示的時候就是表明成功了。
2.查看鏡像:
docker images
3.使用這個鏡像建立一個容器(也能夠稱爲鏡像實例):
語法: docker run --name 這個鏡像實例的名字 -e MYSQL_ROOT_PASSWORD=mysql根用戶的密碼 -d -p 主機端口:容器內部的端口 mysql:標籤 (MYSQL_ROOT_PASSWORD=123456 =號不要有空格間隔) (-d表明後臺運行,-p是爲了把容器內部的mysql綁定到外部端口進行使用) 具體示例: docker run --name testmysql -e MYSQL_ROOT_PASSWORD=123456 -p 3306:3306 -d mysql:5.7
4.查看容器運行狀態:
docker container ls
5.測試鏈接,因爲咱們使用了-p 3306:3306
,這是將容器內部的3306端口與主機的端口創建的鏈接,,因此能夠直接經過鏈接主機Linux的端口來操做容器內部的mysql:
假設當前個人機器的IP是192.168.48.129
,那麼我須要鏈接192.168.48.129:3306
來操做數據庫,請使用你的mysql鏈接工具來測試吧😀。
你作完這個實驗後,你應該能感覺到你大大的節省了安裝mysql和部署mysql的功夫,而若是咱們建立了一個包含了咱們的應用的鏡像,那麼部署咱們的應用的人也能大大減小部署的難度和節省大量的時間。
另外,咱們還引出了鏡像和容器的概念,這將在下面講。
上面引出了鏡像和容器的概念,下面講一下。
docker hub
就是一個知名的倉庫註冊服務器,就好像github是個代碼託管中心同樣。經過一個例子把上面的概念串聯起來:
假設咱們須要拉取一個tomcat鏡像。
首先,咱們指定這個鏡像的倉庫在docker hub,而後搜索一下是否有這個倉庫,而後指定從這個拉取鏡像的哪一個版本(tag),而後把它從倉庫上拉取下來;
鏡像拉取下來以後,使用這個鏡像來生成一個容器,這個容器是怎麼能夠在docker上面運行的呢?這些鏡像都會帶有能夠支撐它運行的操做系統,一個較小的操做系統也就10+M,這些操做系統運行在docker上,而裏面的應用運行在各自的操做系統上。(你能夠這樣類比,docker = vmware,鏡像 = vmx文件,容器= vmware對vmx文件運行起來以後的包含了咱們的應用的操做系統)
上面的步驟運行起來了一個容器,你能夠對這個容器進行操做。(就好像我在簡單使用例子一節中講述的那樣)假設你對了這個容器進行了修改,而後你想提交給別人,該怎麼作呢?(這裏只是文字概念,詳情參考下面的把鏡像推送到阿里雲)
首先,你須要在一個倉庫註冊服務器中建立本身的倉庫,而後在docker中進行登陸操做,並基於修改的容器生成一個鏡像,把這個鏡像推送到倉庫上。而後別人就能夠從你的倉庫中拉取下鏡像了,若是你的倉庫是個開放的倉庫的話。
docker version
或者docker -v
,會返回安裝的docker的版本。docker info
docker search 鏡像關鍵字
,例如docker search mysql
。你除了在命令行中搜索,也能夠在docker hub
上搜索鏡像。
docker search 鏡像關鍵字 -s 數字A
:列出start數不小於指定數字A的鏡像。【若是提示--star過時,那麼使用 docker search 鏡像關鍵字 -filter=stars=數字A
】【star相似於github中的star,也表示這個鏡像的受歡迎程度】docker search 鏡像關鍵字 --no-trunc
:完整顯示鏡像的描述Descriptiondocker search 鏡像關鍵字 --automated
:只列出automated build類型的鏡像。若是你在docker hub上搜索鏡像, 那麼首先進入docker hub(https://hub.docker.com/),而後裏面有個搜索框。搜索mysql以後你能夠看到mysql相關的鏡像,隨便點進去一個,你能夠看到這個鏡像的Description(描述),Tags(能夠看到有什麼版本),Reviews(評價),而在鏡像的旁邊會有一個
docker pull xxxx
(xxxx是鏡像的名字),這個就是教你怎麼拉取鏡像。(拉取下面講)
docker pull 鏡像名:tag
。
:tag
是可選的,tag表示標籤,多爲軟件的版本,默認是latest。好比docker pull mysql:5.7
就表明拉取5.7版本的mysql鏡像。docker images
docker images -a
:顯示全部鏡像(包含中間映像層)。中間映像層的意思是,一個鏡像多是由多層鏡像層疊而來的,這中間的部分就是中間映像層。(這個知識與鏡像的實質有關,何時再寫一章單獨分析。)docker images -q
: 只顯示ID,不顯示鏡像名。docker images --no-trunc
: 顯示完整的鏡像信息,主要是完整顯示了Image ID,就跟git的版本ID差很少,短的ID也能夠用來標識鏡像。docker images --digests
: 顯示鏡像的摘要信息。每個機器上拉取下來的同一個鏡像生成的鏡像ID是不同的,只有摘要才能判斷他們是不是同一個鏡像。docker rmi 鏡像的ID
或者docker rmi 鏡像名:tag
docker rmi 鏡像的ID1 鏡像的ID2
或者docker rmi 鏡像名1:tag 鏡像名2:tag
docker rmi ${docker images -qa}
,這是把docker images -qa的結果做爲刪除鏡像的參數。-f
:強行刪除鏡像docker run [鏡像ID]或[鏡像名:tag]
--name 容器的名字
:定義容器的名字--detach
或-d
:讓容器後臺運行-p 主機的端口:容器的端口
:將容器的端口綁定到主機的端口
主機的端口:容器的端口
,還能夠是IP:主機的端口:容器的端口
、IP::容器的端口
、容器的端口
-P
:隨機對容器開放的端口進行綁定。容器開放的端口是須要聲明的,好比tomcat鏡像中會聲明開放端口8080。隨機綁定就會把聲明的端口隨機與主機端口綁定。--env
或-e
:設置容器的環境變量,有些容器須要環境變量來設置一些數據,好比mysql的初始密碼。docker run --name testmysql -e MYSQL_ROOT_PASSWORD=123456 -p 3306:3306 -d mysql:5.7
docker run [鏡像ID]或[鏡像名:tag] 命令
,這個會在啓動容器以後,幫咱們執行咱們指定的命令。好比docker run -t centos:7 top
就會在啓動centos容器後,幫咱們執行top
,此處我沒用使用-i因此會當場看到top命令的執行。【這個當心使用吧,由於有時候可能會覆蓋容器內部的一些命令,好比若是你在運行mysql鏡像時額外執行命令,那麼將會致使這個容器沒法運行,這將在Dockerfile處講解】docker ps
。
docker ps -a
查看全部容器,包括沒有在運行的。docker ps -l
查看最近建立的容器(一個)docker ps -n 數字
查看最近建立的n個容器docker ps -q
:只顯示容器IDdocker ps --no-trunc
:只顯示容器IDdocker logs 容器名稱或者容器的ID
,有時候容器的啓動問題就要依靠日誌來解決,容器的故障信息都會顯示在日誌中。有些應用會把應用的運行日誌寫在容器日誌中,但有些會寫在容器內的文件中。
docker logs -t 容器名稱或者容器的ID
:加入時間戳docker logs -f 容器名稱或者容器的ID
:持續打印docker logs --tail 數字 容器名稱或者容器的ID
:顯示最後多少行日誌docker logs --since 時間 容器名稱或者容器的ID
:查看什麼時間的日誌,時間能夠是30m
,1h
,或者2020-02-02
,或者2013-01-02T13:23:37
(UTC統一時間),是從何時開始的意思,會從指定時間取到如今。docker stop 容器名稱或者容器的ID
docker start 容器名稱或者容器的ID
docker contatiner rm 容器名稱或者容器的ID
,容器必須先中止才能被刪除
docker rm -f ${docker ps -a -q}
docker ps -a -q | xargs docker rm
docker exec 容器名稱或者ID 命令
,
docker exec -it 容器名稱或者ID linux命令
:-it
能夠說是進入了交互界面,而沒有-it
的時候只是發了一個請求,顯示的只是請求的結果。-t
:在新容器內指定一個僞終端或終端。-i
:容許你對容器內的標準輸入 (STDIN) 進行交互。it能夠分開使用。docker exec testmysql echo hello
docker attach
,與docker exec -it
的效果有點相似。但它進入的實際上是容器啓動時最後執行的命令。
docker run -td centos:7 top
,建立容器的時候執行了一個top命令,那麼attach進入的就是這個top命令,若是你執行的是其餘命令,attcach也是進去那個命令的狀況下。因此可能有些容器你attach進去是一片空白。【當你在attach中關閉了這個容器最終運行的進程的時候(注意,是關閉,退出並不表明必定關閉),這個容器可能會自動關閉,由於你關閉了他的前臺進程。若是你是在終端命令下,可使用ctrl+p+q
來退出容器但不關閉終端,退出直接用exit。】docker port 容器名稱或者ID
docker top 容器名稱或者ID
docker inspect 容器名稱或者ID
,會顯示容器名稱、容器數據存儲位置、網絡設置、環境變量、容器卷等信息。docker cp 本地文件路徑 容器ID:容器路徑
docker cp 容器ID:容器路徑 本地文件路徑
docker build
【Dockerfile的內容,後面講】docker commit
【生成新鏡像的內容,後面講】docker --help
當你學完上述的命令的時候,你應該能理解以前的簡單使用例子中的那些命令的意義了。
上述命令講解中,簡單例子中沒用到的命令,也講述了基本用法。
下面將是一些稍微深刻一點的內容。
How to use this image
模塊看到:當一個容器發現本身無事可作的時候就會自動狗帶(自殺)。
好比說你運行centos容器:docker run centos:7
那麼你會發現這個容器一啓動就自動中止了。這是由於centos內部並無前臺進程,若是docker檢測到這個容器沒有前臺進程,那麼就會自動關閉這個容器。
docker run -td centos
這句命令可讓centos不自動中止,由於使用-t就爲這個容器建立一個前臺進程/bin/bash
,平時使用-it的時候,會直接進行交互,咱們去掉-i和加上d,使得這個交互終端掛起,不立刻交互。
後面咱們再想交互的時候,可使用docker attach 容器ID
或者docker exec -it 容器ID 命令
來進行交互。
上面說了attach的使用注意事項,因爲這裏又涉及了attach,再說一遍:
- 進入容器:
docker attach
,與docker exec -it
的效果有點相似。但它進入的實際上是容器啓動時最後執行的命令。- 好比說
docker run -td centos:7 top
,建立容器的時候執行了一個top命令,那麼attach進入的就是這個top命令,若是你執行的是其餘命令,attcach也是進去那個命令的狀況下。因此可能有些容器你attach進去是一片空白。【當你在attach中關閉了這個容器最終運行的進程的時候(注意,是關閉,退出並不表明必定關閉),這個容器可能會自動關閉,由於你關閉了他的前臺進程。若是你是在終端命令下,可使用ctrl+p+q
來退出容器但不關閉終端,退出直接用exit。】
解決自動狗帶這個問題的方法就是把你的應用之前臺的方式來運行,又或者建立一個額外的前臺進程,因此對於那些是後臺運行的應用要注意
在執行docker命令的時候,有時候docker還沒啓動,那麼可能會報一個這樣的錯誤。
你應該看到了一個docker daemon,daemon在計算機領域一般是守護進程的意思,下面咱們來介紹一下這個的意義。
docker是一種Client-Server結構的系統,其實咱們對於docker的全部操做都是守護進程來幫咱們發送給docker的,咱們平時運行命令實際上是在Docker Client,Docker Client經過命令行與Docker Damon通訊,完成Docker相關操做。
咱們表面上操做docker,但實際上,咱們只是操做守護進程,守護進程來幫咱們發送命令。
docker run -it -v /宿主機路徑:/容器內路徑 鏡像名
docker run -it -v /宿主機路徑:/容器內路徑:ro 鏡像名
,默認建立的容器卷是兩邊均可讀可寫的,加上ro以後,是容器只讀,主機可讀可寫。docker volume create 容器卷名稱
/var/lib/docker/volumes/hello/_data
docker volume inspect 容器卷
名稱來查看docker volume inspect 容器卷名稱
docker volume ls
-q
只顯示容器卷名稱docker volume prune
,會移除沒有被容器使用的容器卷。docker volume rm 容器卷名稱
可使用--volumes-from
來繼承另外一個容器的容器卷。
好比:
先執行:docker run --name centos1 -itd -v /outpath:/containerpath centos:7
再執行:docker run --name centos2 -itd --volumes-from centos1 centos:7
而後再執行:docker exec -it centos2 cat /containerpath/a
你就能夠看到centos2中也配置了容器卷/outpath:/containerpath
,也就是說,centos2繼承了centos1的容器卷。
docker commit
經過容器來生成一個新的鏡像。docker build
來建立鏡像。1.好比說咱們能夠拉取一個tomcat鏡像,而後生成一個容器;
docker pull tomcat:8.0
2.啓動這個容器:
docker run --name mytomcat -d -p 8888:8080 tomcat:8.0
3.對容器進行一些自定義的修改,咱們這裏把咱們的一個很是簡單的應用部署到tomcat上。【這個war是我從一個structs的jar包下弄的,是一個很乾淨的war,適合用來作實驗】war下載地址
docker cp 本地文件路徑 容器ID:容器路徑
命令把咱們的war包複製到tomcat中。docker cp /struts2-blank.war mytomcat:/
docker exec -it mytomcat /bin/bash
root@9ce9d01569e6:/usr/local/tomcat# cp /struts2-blank.war webapps/
docker restart mytomcat
cd /usr/local/tomcat/bin/
下執行shutdown.sh,你就會發現沒過一會,容器就自動中止了。】http://主機地址:8888/struts2-blank
就能夠訪問到那麼如今,這個容器能夠說已經有了咱們的應用了,那麼怎麼基於這個容器來建立新的鏡像,以方便經過鏡像來方便部署到一臺臺機器上呢?
4.而後提交鏡像。
docker commit 能夠提交容器副本,使之成爲一個新的鏡像。
命令:docker commit -a "做者名" -m "提交說明" 容器名稱或id 打包的鏡像名稱:標籤
選項說明:
-a :提交的鏡像做者;
-c :使用Dockerfile指令來建立鏡像;
-m :提交時的說明文字;
-p :在commit時,將容器暫停。
[root@localhost /]# docker commit -a "progor" -m "簡單的新鏡像測試" mytomcat mytomcat2:1.0 sha256:a3393dbf9326d0f065d6ee8d757c6d7c1050df8a513e6a52286b4af91154806b
5.查詢一下本地鏡像列表,能夠看到咱們剛剛建立的鏡像:
6.咱們基於這個鏡像來建立一個新的容器看看,看是否是有咱們的應用了:
docker run --name mytomcat2 -d -p 8889:8080 mytomcat2:1.0
7.而後再在外部訪問一下http://主機地址:8889/struts2-blank
,能夠訪問,證實了新的鏡像包含了咱們以前部署的應用。
使用Dockerfile其實也是經過修改已有鏡像來建立新鏡像,但它把修改的命令都存儲到Dockerfile中了。Dockerfile比手動修改更方便管理。
下面列一個mysql 5.7的示例Dockerfile,因爲篇幅問題,這裏就不直接列了,請參考下列連接,而後介紹一下以後,咱們就學習相關的命令。
mysql/5.7/Dockerfile
上面的示例的內容也比較長,我不會全部都講,只會講基本流程。
從上面的流程來看,其實就是引入了一個基礎的鏡像以後,配置環境變量等各類參數,其實也就是講咱們以前的手動的操做換成了換成命令寫在了Dockerfile了。
FROM debian:buster-slim
【來自 mysql/5.7/Dockerfile 】RUN 命令
或者RUN ["可執行文件"," 參數1","參數2"]
,例如:RUN ["/bin/bash", "-c", "echo hello"]
RUN 命令
是在shell中執行的,會作Shell處理,多行命令,可使用\
分行。RUN ["可執行文件","參數1","參數2"]
是非SHELL的,因此它不會進行上下文變量解析,例如RUN [ "echo", "$HOME" ]
RUN groupadd -r mysql && useradd -r -g mysql mysql
【來自 mysql/5.7/Dockerfile 】docker inspect
命令來查看。docker run --env 環境變量名=變量值
能夠在運行時指定環境變量。會覆蓋默認的環境變量。$變量名
或者${變量名}
來獲取指定環境變量的值。ENV TINI_VERSION 0.14.0
【來自jenkins/Dockerfile 】和
${foo}`文字。ENV abc=bye def=$abc
USER <user>[:<group>]
或者 USER <UID>[:<GID>]
USER ${user}
【來自jenkins/Dockerfile 】/
WORKDIR /data
【來自 redis/6.0-rc/Dockerfile 】COPY [--chown=<user>:<group>] <src> <dest>
將文件從路徑 <src>
複製到容器路徑 <dest>
中。COPY docker-entrypoint.sh /usr/local/bin/
【來自 redis/6.0-rc/Dockerfile 】ADD [--chown=<user>:<group>] <src> <dest>
:將文件從路徑 <src>
複製到容器路徑 <dest>
中,並解壓。[--chown=<user>:<group>]
是可選的,用於修改文件的所屬用戶或所屬組,但僅使用與Linux容器VOLUME /data
【來自 redis/6.0-rc/Dockerfile 】docker run
中有說到能夠隨機端口綁定,容器怎麼知道爲咱們綁定哪些容器內部的端口呢,就是經過expose知道的。EXPOSE <port> [<port>/<protocol>...]
EXPOSE 80/tcp
或EXPOSE 80/udp
,默認使用TCPEXPOSE 6379
【 redis/6.0-rc/Dockerfile 】CMD ["可執行命令或文件","param1","param2"]
,CMD ["param1","param2"]
,CMD 命令 param1 param2
CMD ["redis-server"]
,CMD [ "sh", "-c", "echo $HOME" ]
,CMD echo hello
,CMD ls -a
,CMD ["ls","-a"]
ONBUILD RUN echo hello
LABEL <key>=<value> <key>=<value> <key>=<value> ...
MAINTAINER 建立者
如今推薦使用LABEL maintainer="建立者"
LABEL OWNER="所屬者"
docker inspect
命令。LABEL maintainer="SvenDowideit@home.org.au"
【官方文檔示例】ENTRYPOINT ["docker-entrypoint.sh"]
【來自 redis/6.0-rc/Dockerfile 】${group}
來獲取。ARG user=jenkins
【來自jenkins/Dockerfile 】# add gosu for easy step-down from root
\
來分行。cd "$OPENSSL_PATH"
應用
意義。RUN能夠隨便建立一個目錄,或許作的只是一些運行的前置工做;但ENTRYPOINT裏面應該與這個容器前臺進程(應用)的運行更加相關,好比定義如何啓動應用。固然你也可使用RUN建立前臺進程😓。。。CMD ["mysqld"]
,而前面有ENTRYPOINT ["docker-entrypoint.sh"]
,這將會在執行docker-entrypoint.sh的最後執行mysqld
,內部有沒有再處理mysqld,就要看具體的docker-entrypoint.sh了。這是一個流行用法,因此你能夠在不少Dockerfile中看到"docker-entrypoint.sh"1.咱們根據以前的「修改已有鏡像」的例子來寫一個Dockerfile:
# 繼承基礎鏡像 FROM tomcat:8.0 # 把war包拷貝進去 COPY struts2-blank.war / # 把容器內的war包複製到容器的tomcat中 WORKDIR $CATALINA_HOME RUN cp /struts2-blank.war webapps/ # 指定端口,端口也會繼承下來,因爲咱們也使用同樣的端口,其實能夠省略EXPOSE # EXPOSE 8080 # 啓動tomcat,基礎鏡像的CMD會繼承下來 因此其實下面的CMD能夠省略,除非你要執行另外的命令 # CMD ["catalina.sh", "run"]
2.執行docker build 建立一個鏡像:
docker build -t mytomcat3:1.0 .
3.經過這個鏡像建立一個容器:
docker run --name mytomcat3container -d -p 8888:8080 mytomcat3:1.0
4.測試訪問:
http://主機地址:8888/struts2-blank
5.結果是能夠訪問的,說明咱們使用Dockerfile實現了以前基於容器修改生成鏡像的效果。
下面的基原本自阿里雲的官網教程,只不過加了配圖。
語法: $ sudo docker login --username=用戶名 倉庫註冊服務器 示例: $ sudo docker login --username=10086 registry.cn-shenzhen.aliyuncs.com
語法: 1.登陸 $ sudo docker login --username=用戶名 倉庫註冊服務器 2.建立tag: $ sudo docker tag 鏡像ID 倉庫註冊服務器/用戶名/鏡像名:[鏡像版本號] 3.推送鏡像: $ sudo docker push 倉庫註冊服務器/用戶名/鏡像名:[鏡像版本號]
docker tag 用於重命名鏡像,下面的就把本地的一個鏡像重命名了。
而後你就能夠在倉庫管理頁看到這個鏡像了。
語法: $ sudo docker pull 鏡像地址 示例: $ sudo docker pull registry.cn-shenzhen.aliyuncs.com/用戶名/鏡像名:[鏡像版本號]
這一篇文章,其實講的東西仍是很淺的。還有不少東西都沒用講。
但對於基本使用場景應該仍是能夠應付的。(固然,😄容器管理、swarm、k8s並無講)
還有不少技術沒講,後面有空再寫吧。。。咕咕咕。