最近給部門同事培訓docker相關的東西,把我的培訓內容總結下,發到博客園上,和大家一起分享。我的培訓思路是這樣的
首先講解docker的安裝、然后講下docker的基本的原理,最后講下docker的使用,基本上讀完這篇博客大家一定可以基本上掌握docker了;其實我的想法是這樣的,docker就是一個工具,我們把docker的使用搞定后,對底層原理大概了解一二就可以了,沒有必要深究,下面進入正題
一、docker的安裝
1、替換yum源和docker源
wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.163.com/.help/CentOS7-Base-163.repo |
wget http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
|
2、清空yum緩存和重新生成緩存
yum clean all yum makecache
|
3、通過yum的方式安裝docker-ce
yum install docker-ce-20.10.6 -y |
4、編寫docker開機自啟動腳本
[root@mylinux init.d]# pwd /etc/init.d [root@mylinux init.d]# cat startdocker.sh #! /bin/bash #chkconfig: 345 88 14
#decription:startdocker /usr/bin/systemctl start docker
|
5、設置開機自自動
[root@mylinux init.d]# pwd /etc/init.d [root@mylinux init.d]# chkconfig --add startdocker.sh [root@mylinux init.d]# chkconfig startdocker.sh on
|
6、設置linux的內核流量轉發
touch /etc/sysctl.d/docker.conf |
文件內容如下
[root@mylinux ~]# cat /etc/sysctl.d/docker.conf net.bridge.bridge-nf-call-ip6tables = 1 net.bridge.bridge-nf-call-iptables = 1 net.ipv4.conf.default.rp_filter = 0 net.ipv4.conf.all.rp_filter = 0 net.ipv4.ip_forward = 1
|
設置該修改生效
modprobe br_netfilter sysctl -p /etc/sysctl.d/docker.conf |
7、啟動docker即可,至此docker安裝完成
二、docker的原理和概念講解
1、虛擬機的弊端?
之前的虛擬化都是通過虛擬一個完整的虛擬機的方式,每個獨立的計算機的擁有獨立的底層物理硬件,操作系統和應用程序執行的完整的環境;就比如我們公司的虛擬化平台,就是通過kvm+qemu的開源的方式提供整套虛擬機的解決方案
qumu 主要用來工作在用戶空間,他本身支持所有的硬件設備的模擬,包括cpu和內存、磁盤、網卡、顯卡等,欺騙guestOS的認為自己直接在和硬件打交道,其實guestOS
是在和qemu模擬出來的硬件打交道,qemu會把guestOS的指令翻譯后給真正的硬件進行操作,通過這種方式,guestOS可以直接和host的硬件設備做交互,但是由於所有
的guestOS的指令都需要通過qumu的翻譯,因此性能會比較差
kvm實際是由linux內核提供的虛擬化架構,kvm本身需要處理器本身支持虛擬化技術,比如inter-vt和amd-v技術,在linux2.6內核后,kvm已經合入主干中
kvm 本身不實現任何模擬,他提供一個/dev/kvm的接口,這個接口可以被host主機用來創建vcpu和運行,vcpu的寄存器的讀寫、虛擬內存的創建和分配。有了
kvm后,guestOS的cpu指令就不需要經過QEMU來翻譯變可以直接運行,大大提高了運行速度,但是kvm本身只支持cpu和內存的虛擬化,所有他必須要結合qume
才能構成一個完整的虛擬化方案
所以為了讓虛擬機中的程序實現像在真實物理機上運行的近似效果,不僅僅會帶來極大的資源浪費,一個宿主機可能只能運行幾個虛擬機,同時虛擬機對cpu還有特殊要求;另外虛擬機動輒十幾G,管理和備份起來就非常困難;
所以容器技術的作為一個虛擬化另外一個解決方案,代替虛擬機成為新的趨勢;
我們今天講的docker其實是一個容器技術的一個最流行的解決方案;
2、容器的優勢
docker是用goland語言開發的,基於linux內核的Cgroup。Namespace以及unionFS等技術,對進程進行封裝隔離,屬於操作系統層面的虛擬化技術
a、容器是一個輕量級的隔離系統,可以更高效的利用硬件資源,同樣一個宿主機,最多可以跑幾個虛擬機,但是可以跑上百個容器
b、kvm虛擬化需要硬件cpu虛擬化的支持,而容器根本就不需要
c、容器所占用的空間相比虛擬機非常小,更容易管理和備份
容器內的應用程序是直接運行在宿主機的內核上的,能夠使用宿主機的最大的硬件資源,容器內沒有自己的內核,也沒有對硬件進行虛擬,因此容器比虛擬機更加輕便,docker引擎容器僅包含應用及其依賴,
他在主機操作系統的用戶空間作為一個獨立的進程運行,與其他容器共享內核,因此,他得到了虛擬機的資源隔離和分配好處,更方便和高效
3、docker平台組成
docker客戶端主要為我們提供操作容器和鏡像的入口
docker服務端主要是為我們管理容器和鏡像
dockerhub就和gitlab一樣,為我們在雲端管理鏡像,我們可以通過dockerhub上傳、下載鏡像
4、docker引擎的構成
Docker引擎是C/S架構的
5、 images(鏡像)
鏡像是一個只讀模板,用於創建容器,也可以通過dockerfile文本描述鏡像的內容創建容器,也可以直接dockerhub上拉取鏡像;
鏡像的概念類似於編程開發中的面向對象的類,而容器就是這個類的示例
構建容器的過程,就是運行鏡像,生成容器的實例
鏡像的分層架構
bootfs主要包括bootloader和kernel,bootloader主要是引導加載kernel,linux剛啟動時會加載bootfs文件系統
baseimage,在bootfs之上,包含的就是典型的linux系統中的/dev ,/bin、等標准目錄和文件系統的rootfs,也就是我們常說的各種不同操作系統的發行版,比如ubuntu,Centos等發行版
當通過一個image啟動一個鏡像,docker會在該images最頂層,添加一個讀寫文件系統作為容器,然后運行該容器
docker容器的本質是基於UnionFS管理的分層文件系統;
我們查看docker鏡像,為什么一個linux發行版只有幾百兆?因為docker鏡像只有rootfs和其他鏡像層,不包括宿主機的內核文件系統,因此很小。
那為什么我們查看一個nginx鏡像,需要一百多兆,但是一個nginx其實只有幾kb?因為docker鏡像是分層,nginx的確很小,但是一個用於運行nginx的鏡像文件,依賴父鏡像就比較大大了。
6、container(容器)
容器是一個鏡像運行的實例
創建容器的的過程
a、獲取鏡像,如docker pull centos從鏡像倉庫拉取,或者自己通過dockerfile創建
b、使用run命令啟動一個容器
c、分配文件系統,掛載一個讀寫層,在讀寫層加載鏡像
d、分配網絡和網橋接口,創建一個網絡接口,讓容器和宿主機通信
e、容器獲取ip地址
f、執行容器的命令,如/bin/bash
g、返回容器啟動結果
7、dockerhub(鏡像倉庫)
docker的鏡像需要管理,docker提供了Registry倉庫,其實他也是一個容器,
8、dockerfile
將創建鏡像寫成一個腳本,docker build命令就會執行dockerfile中的指令來創建鏡像
dockerfile鏡像的描述文件,包含以下指令,后面我們重點講解,這里簡單了解即可
FROM 定義基礎鏡像
MAINTAINER 作者
RUN 運行linux命令
ADD 添加文件/目錄
ENV 設置環境變量
CMD 運行鏡像要執行命令
三、docker命令講解
1、平台相關命令
查看docker版本
docker --version
查看docker服務狀態
systemctl status docker #查看docker服務狀態 systemctl stop docker #關閉docker服務 systemctl start docker #啟動docker服務 systemctl restart docker #重啟docker服務
docker info |grep Root #查看docker的鏡像存儲位置
2、docker鏡像相關命令
搜索鏡像
docker search centos
從dockerhub拉取鏡像
docker pull centos
查看本地的docker鏡像
docker images
查看本地鏡像,只顯示鏡像ID
docker images -q
刪除本地鏡像,可以通過名稱刪除,也可以通過鏡像id刪除
docker rmi centos
查看鏡像相關信息
docker image inspect 5d0da3dc9764
3、Dockerfile相關命令:如果你想自定義鏡像內容,就需要自己寫腳本,這里的腳本也就是Dcokerfile
定制鏡像其實有兩種方法
1、手工修改容器的內容,然后導出容器為鏡像
2、基於dockerfile自行編寫指令,基於指令流程創建鏡像
下面介紹下Dockerfile中的常見指令
FROM 基礎鏡像信息,提供rootfs的功能
MAINTAINER 鏡像的作者信息,可以不寫
RUN 制作鏡像的指令,也就是在docker內執行的linux的命令,每個RUN 就相當於一層鏡像,所以盡量把命令寫在一個RUN中,不然鏡像就會很大
ADD 拷貝宿主機本地的文件到鏡像內
COPY 拷貝宿主機的本地的文件到鏡像內容,如果tar.gz\zip\xz類型的會自動解壓,這也是COPY指令和ADD的區別
WORKDIR 類似於linux中的cd命令,切換工作目錄
USER 用於改變用戶,和linxu中的切換用戶的功能是一樣的
VOLUME 這里可以指定一個鏡像內部的目錄,docker會把這個目錄掛載到宿主機的某個目錄下,這個后面我們查看鏡像信息就可以看到他掛載的宿主機的哪個目錄了
容器運行的時候,應該保證存儲層不要寫入任何數據,運行容器生成的數據,我們推薦是掛載的方式,寫入到宿主機上,進行維護
EXPOSE 設置鏡像對外打開的端口
ENV 設置環境變量,通過ENV設置的環境變量在鏡像啟動為容器后繼續生效
ARG 設置環境變量,通過ARG設置的環境變量在鏡像啟動為容器后就不在生效
CMD 指定容器啟動后要干的事情
下面看一個Dockerfile的例子
FROM centos MAINTAINER hellodocker RUN echo "this is my first docker images" RUN mkdir /data VOLUME /data ADD abc.txt /data COPY abc.tar.gz /data ENV name = "hello world" ARG add RUN echo ${name} ARG age="12" RUN echo ${age} WORKDIR /data CMD ["/bin/bash"]
這里要注意這個問題
a、通過add、copy命令拷貝的文件要在和dockerfile相同的目錄下
b、利用arg定義的命令,key和value之間的等號要沒有空格,不然會跑錯
c、另外使用arg參數可以接受build傳的參數
比如我們在docker這樣寫
在構建的時候就需要這樣構建
下面就是我們構建的過程
[root@mylinux docker]# docker build --build-arg add="sz" ./ Sending build context to Docker daemon 6.144kB Step 1/14 : FROM centos ---> 5d0da3dc9764 Step 2/14 : MAINTAINER hellodocker ---> Running in 71362c2a7dd5 Removing intermediate container 71362c2a7dd5 ---> d18802a8f3b0 Step 3/14 : RUN echo "this is my first docker images" ---> Running in 6d7e2fe3f3ec this is my first docker images Removing intermediate container 6d7e2fe3f3ec ---> 6fe7890d4db3 Step 4/14 : RUN mkdir /data ---> Running in 4fe2cb44c769 Removing intermediate container 4fe2cb44c769 ---> 5625a2c2d32f Step 5/14 : VOLUME /data ---> Running in 566bcc7901ae Removing intermediate container 566bcc7901ae ---> a5fb2e009365 Step 6/14 : ADD abc.txt /data ---> 9fff6fff0e03 Step 7/14 : COPY abc.tar.gz /data ---> 6305fe28d70c Step 8/14 : ENV name = "hello world" ---> Running in 19894058bf3d Removing intermediate container 19894058bf3d ---> b8cef325887e Step 9/14 : ARG add ---> Running in ca3b757fd0f8 Removing intermediate container ca3b757fd0f8 ---> 974e2b0586fa Step 10/14 : RUN echo ${name} ---> Running in 3d2e2b5d8d2e = hello world Removing intermediate container 3d2e2b5d8d2e ---> 1a6805e71aca Step 11/14 : ARG age="12" ---> Running in b4002f463007 Removing intermediate container b4002f463007 ---> 4c6b01d13609 Step 12/14 : RUN echo ${age} ---> Running in b98d429ba25f 12 Removing intermediate container b98d429ba25f ---> 8c72f6092704 Step 13/14 : WORKDIR /data ---> Running in a88092bf35f7 Removing intermediate container a88092bf35f7 ---> b3ca82aa4440 Step 14/14 : CMD ["bin","bash"] ---> Running in 9003133696dc Removing intermediate container 9003133696dc ---> 47afe19c79df Successfully built 47afe19c79df
此時如果我們docker images查看docker鏡像,這個鏡像是沒有名稱的
我們可以在構建的時候加個tag字段知名
[root@mylinux docker]# docker build --build-arg add="sz" --tag "firstimage" ./
此時在查看我們的鏡像
4、容器相關的命令
上面我們已經構建了一個鏡像,下面我們就基於這個鏡像進行容器相關的命令學習
docker ps
docker ps #查看當前啟動的容器 docker ps -a #查看曾經啟動過的容器
docker rm 容器ID
docker rm 389de141edf2 #刪除容器的啟動記錄
docker run -it myimage
docker run -it 鏡像名稱 #前台運行鏡像,並分配一個終端
docker container inspect 72dacd386293
docker container inspect 72dacd386293 #查看容器的相關屬性信息
docker run -it myimage ping www.baidu.com
docker run -it myimage ping www.baidu.com #啟動容器,並在容器內執行對應命令
docker run -d myimage
docker run -d myimage #后台啟動容器
我們通過宿主機的linux命令可以看到容器的ip地址
docker top 640a0ba6125b
docker top 640a0ba6125b #同linux后台top命令
docker exec -it 640a0ba6125b ip a
docker exec -it 640a0ba6125b ip a #進入一個啟動的容器,並執行相關命令
啟動還有其他參數 -p 端口映射
宿主機的9000會映射到容器的900端口
可以查看轉發情況
docker run -d --name mycontainer myimage ping www.baidu.com
docker run -d --name mycontainer myimage ping www.baidu.com # --name 為容器起一個名字
docker logs 容器id
docker logs ddaa72f7a52f #查看容器的輸出的日志
docker stop 容器id
docker stop #關閉一個容器
可以測試下我們Dockerfile中定義的變量
測試下我們創建的目錄
測試我們掛載的目錄
我們先通過docker container inspect 容器id查看宿主機的掛載的目錄
docker commit
docker commit -a docertest -m "test commit" a068fbd45560 testdocker:v1.0.0 -a :提交的鏡像作者; -m :提交時的說明文字;
docker save
docker save testdocker:v1.0.0 > /data/docker/testdocker.tar 把鏡像文件轉換為本地文件,進行保存和管理
docker load -i
docker load -i testdocker.tar #把本地的鏡像文件變為鏡像
至此,我覺得大家看我的博客,基本上可以滿足日常的工作需要,有需要的朋友可以博客交流,謝謝大家!