1.1 什么是docker
Docker是通過內核虛擬化技術(namespaces及cgroups、cpu、內存、磁盤io等)來提供容器的資源隔離與安全保障等。由於Docker通過操作系統層的虛擬化實現隔離,所以Docker容器在運行時,不需要類似虛擬機(VM)額外的操作系統開銷,提高資源利用率。
1.2 docker自理解
相當於一個虛擬的應用打包器,但他屬於一個進程,封裝成一個鏡像。
1.3 docker分為兩大版本
docker ce、ee 社區版、企業版(收費)
1.4 Docker的主要目標是(構建,運輸,處處運行)
構建:做一個docker鏡像
運輸:docker pull
運行:啟動一個容器
每一個容器,他都有自己的文件系統rootfs
1.5 linux容器技術,容器虛擬化和kvm虛擬化的區別
1.5.1 kvm虛擬化
需要硬件CPU的支持,需要模擬硬件,可以使用不同的操作系統,啟動時間分鍾級
1.5.2 容器虛擬化
嚴格來說只是進程之間的隔離,不需要模擬硬件,共用宿主機的內核,啟動時間秒級
1.6 docker容器虛擬化的好處
快速部署、輕松遷移、資源利用率高
1.7 Docker主要組件
鏡像、容器、倉庫
1.8 Docker是傳統的C/S架構
分為docker client和docker server
使用命令:docker version #可查看服務端與客戶端,當服務端啟動失敗時,使用docker version會只看到客戶端,會有報錯。
1.9 docker環境准備
准備兩台純凈的Centos7的虛擬機:
主機名 |
IP |
配置 |
Oldboy-docker01 |
10.0.0.11 |
1核2g內存 |
Oldboy-docker02 |
10.0.0.12 |
1核2g內存 |
1.10 Docker的安裝
wget -O /etc/yum.repos.d/docker-ce.repo https://mirrors.ustc.edu.cn/docker-ce/linux/centos/docker-ce.repo #下載他的repo文件
sed -i 's#download.docker.com#mirrors.ustc.edu.cn/docker-ce#g' /etc/yum.repos.d/docker-ce.repo #因為上面下載的repo文件指向的是國外的docker官網源,國內網速下載國外會很慢,這里替換成中國科學技術大學的源地址去下載。
1.10.1 也可用yum安裝
yum install docker-ce –y
rpm –qa|grep docker #最后安裝完后,看一下是否安裝了。
實在不行就:yum install -y docker 直接點。
1.10.2 使用阿里雲docker加速器下載(速度快、免費)
https://cr.console.aliyun.com/cn-beijing/mirrors
點擊鏡像加速器-CentOS-按照下面的提示把文件寫入與重啟docker服務
或執行以下操作:
mkdir -p /etc/docker
tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://r1ztx9gb.mirror.aliyuncs.com"]
}
EOF
systemctl daemon-reload
systemctl restart docker
1.11 Docker啟動
systemctl start docker #首先啟動docker
1.12 啟動第一個容器
docker run -p 80:80 nginx #正在運行的時候,其實正在下載nginx最新版的鏡,上面操作已經使用了阿里雲的docker加速器,所以這邊會很快下載完,前提不能被之前其他服務占用80端口,否則啟動不了docker的nginx。 啟動后,使用其他機器訪問nginx,docker機器會出現日志,方便提示的作用。
1.13 docker鏡像的常用管理命令
搜索鏡像
docker search centos #搜索鏡像
返回結果說明:
鏡像的名字 描述 點贊數 是否是官方的(有OK是官方的) 是否是自動構建的
說明:下載鏡像的時候,優先選擇點贊數比較多的。
下載鏡像
docker search alpine #搜索一個小文件下載測試
docker image pull alpine #鏡像內所有的操作都可用image后在tab查看,image也行,docker pull也性。
docker image ls #查看已經下載了多少個鏡像
查看鏡像
docker images
刪除鏡像
docker rmi
導出鏡像
docker save
例子:docker save alpine:latest >docker-alpine.tar.gz #alpine后面接上最新版本,導出的時候,把他另存為一個tar.gz的包
導入鏡像
docker load
例子:docker image load –I docker-alpine.tar.gz #導出后,再導入,-i是從哪里導入,也可以寫路徑。
注意:導入鏡像也有一個import命令可以導入,但是用這個導入會導致鏡像進不去/bin/bash或sh交互式模式,所以慎重!如果導入了,得重新使用load導入。
docker run nginx #這種效果會一直在前台一直不斷的耗着,跟沒有加&一樣
docker run –d nginx #加了-d參數后就會在后台運行。
1.14 docker的容器管理
docker container inspect #說明書,詳細的意思
說明:上面的是容器的ID地址,下面是容器的名字
docker container inspect 02dea79e52c7|grep -i ipaddr #查看這個容器的IP地址。
curl 172.0.0.0. #查看他顯示出來的IP地址,然后直接curl打開一下,可以訪問到主機,這就是容器通過html產生出來的網頁,這時候只有本地能訪問,外部不能訪問,這就是沒有在運行nginx的時候加上端口的原因。
docker run -d -p 80:80 nginx #我們加上這個端口,相當於docker的端口映射
docker ps #再去查看,會發現nginx最后面哪個80會指向一個80,這就是本地80映射給外部80端口的作用
docker –p端口映射的原理:其就在iptables上加了nat轉換的規則,將80端口,轉向了本地的80端口。
1.14.1 啟動容器
docker run 容器名字 #啟動docker不使用掛起其實是當場死掉,需配合-it交互式夯住來使用才能啟動並掛起來使用這個鏡像。
1.14.2 查看容器進程
docker ps –a #-a是所有容器顯示, 但使用ps命令搜索出來的容器名字是隨機字符串,因為啟動容器時沒有直接指定名字。
例子:docker rm `docker ps -a -q` #批量刪除docker容器,docker ps –a –q參數是顯示容器所有的ID,顯示出來在配合docker刪除命令刪除。
1.14.3 停止容器
docker container stop 容器ID或容器名字
1.14.4 刪除容器
docker container rm 容器的ID
1.14.5 進入容器
docker run –it nginx /bin/bash #參數-i是交互式,參數-t終端,后面加/bin/bash原因是進入容器肯定要執行某些操作,所以要進入/bin/bash
說明:進入容器,相當於進入一個袋子系統類似,一個小型運行系統似的,進入這個小型系統里面大部分命令都沒有,只有一些基礎命令,比如unamr –r或者是查看版本這樣。
docker exec –it 容器的ID或名字 在容器執行的命令
docker 容器只要后面不加命令,只要有返回結果就會秒退,所以要有個命令讓他一直夯着,才能持續正常運行。
簡單來講:啟動一個容器,一定要執行一個命令,不管什么命令,只要不輸出結果讓他一直夯住才能持續正常運行,否則秒退,這個容器的生命周期就沒有了,相當於退出運行了。
1.15 殺掉容器進程
docker kill 容器的ID #這種方式比較強制,因為他底層是一個進程,所以可以直接強制Kill掉。
1.16 讓容器持續在后台運行的方法(docker容器的核心)
docker中的容器,如果想放在后台運行,需要第一個進程是處於一直夯住的狀態,否則這個容器,就會處於退出狀態!(簡單來講就是讓它卡着那不動)
一般不知道在容器里用什么命令,那就指定 /bin/bash進入一個交互模式,就不會回顯效果,並且又能持續正常運行,最好的方式了。
1.17 進入Centos鏡像的容器(說明進入容器參數的利端與弊端)
docker load 導入 進來centos鏡像
docker run –it –name oldboy centos:latest /bin/bash #啟動一個容器,並且為這個容器起一個名字,還能指定版本,最后執行進入鏡像的命令行模式。
ctrl+p 松開再ctrl+q #這樣退出容器,並且容器也還在運行,並不會完全退出,方便切出去處理其他不對的事情再切換回來這個容器繼續操作。
docker attach oldboy #剛才是臨時退出,還想進去就輸入這種命令也可以進入容器
nsenter #這個命令來進入容器,會有些好處。
docker search centos6 #這樣看效果不明顯,所以pull下載一個Centos6和Centos7對比就會有明顯效果。
docker exec –it oldboy /bin/bash #這種進入容器的方式比較好
docker attach oldboy #這種方式進入容器的話,會有弊端。
docker inspect oldboy22|grep -i pid #查看一個容器的PID,在使用nsenter穿越進去這個容器。
nsenter –t 21824 -m -u –i –n –p #通過網絡、像創建一個虛擬機一樣,穿越進去,進去之后像bash類似,但是特點是沒有終端,缺點是環境變量有些不一樣,這種進入容器的方法比較難記憶,只要有個印象即好。
說明:第一種是exec單獨的一個bash進程,不會造成同步操作,使用第二個進入容器的命令的話,就會同時使用一個bash進程,會造成同步,你exit退出了,另外一個attach的進程就會退出了。
1.18 Docker容器的網絡訪問(端口映射)
Docker網絡原理圖與說明
docker run –d –p 0.0.0.0:80:80 nginx:latest #運行一個nginx的容器,並且-d后台運行,並且-p指定映射,將本地的80端口映射到容器里的80端口
換端口再啟動一個nginx實例:
docker run –d –p 0.0.0.0:81:80 nginx:latest #將本機的81端口,映射到容器里的80端口,在外部打開需要指定10.0.0.7:81 而不是80了。
說明:此多端口開容器方法可開多個nginx容器,為了應對沒有docker的情況下,負載均衡到了極限需要擴幾台nginx機器要一大堆繁瑣操作時,就可用這種方法快速啟動部署多個nginx實例來幫忙抗住nginx並發壓力,就不需初始化系統、編譯nginx啥的。
可查看nginx的docker容器占用內存
free –m #幾乎占用的特別少,占用資源特別少,所以docker的好處就展現出來了。
指定多個端口
docker run –d –p 0.0.0.0:8080:80 –p 1122:22 nginx:latest #加多個p參數就可以指定多個端口,1122端口的寫法是本地宿主機的1122端口映射到容器的22端口,后面跟上容器與最新版本。
問題:這邊指定這個容器里的某個端口指定物理機的某個端口,80端口有,但是22端口沒有,這怎么回事呢?
解答:可進入這個容器的bash控制界面,這個nginx鏡像的容器里的小型系統是Ubuntu系統的,所以在進入bash界面后要使用Ubantu的命令,例如apt-get install下載命令等去操作。
容器里啟動sshd會報dbug的錯誤,解決辦法:
說明:上方操作因指定了22端口,所以要用到22端口就必須容器里要有sshd的服務,使用Ubuntu系統的apt-get安裝會出錯,這里使用Centos的容器系統來操作。
docker run –it –p 2022:22 centos:latest /bin/bash #前提必須要下載好Centos的鏡像才能進入,這里啟動進項並且本機的2022端口映射到容器里的22端口,並且進入一個bash控制終端。
yum install –y openssh-server #安裝ssh服務
systemctl start sshd #啟動ssh服務
報錯信息:Failed to get D-Bus connection: Operation not permitted #因為啟動centos容器時Dbus-daemon沒能啟動,所以可去百度找答案,或者進入容器時指定Dbus來連接進去,就不會報錯。(這個原因是因為dbus-daemon沒能啟動。其實systemctl並不是不可以使用,將你的cmd或者entrypoint設置為/usr/sbin/init即可。會自動將dbus等服務啟動起來。)
解決方法: docker run –privileged -d -p 2022:22 -e “container=docker” -v /sys/fs/cgroup:/sys/fs/cgroup centos /usr/sbin/init
docker -ps #找到剛才回顯出來的容器ID
docker exec -it 容器的ID /bin/bash #重新進入這個容器的bash控制台。
ps -ef #查看進程,可看到容器啟動時,啟動的第一個進程是/usr/sbin/init,有了init引導就會啟動dbus-daemon了,有了dbus就能啟動systemctl。
yum install -y net-tools #因為Centos系統是純凈的,所以很多命令都不能用,這里安裝一個命令工具包。
netstat -lntup #隨后才能使用這個命令來查看容器里的端口22開啟沒。
ifconfig #這里使用ifconfig查看容器里的IP是多少。
echo 123456|passwd --stdin root #給容器設置一個密碼,否則沒密碼連接不上。
說明:以上操作都是容器里的Centos進行操作,沒有指定映射端口前,宿主機可連接容器的IP進行連接,只有映射了端口后,才能在其他機器連接宿主機的IP並且指定好端口來連接。(一定要區分好,使用sshd的容器其實也就是套用sshd工具在宿主機里,不要搞混了。)
其他機器連接試一下:
ssh -P2202 root@宿主機的IP #能連接后使用密碼就可以連接上,並且指定好本機映射的IP。
1.19 Docker的數據卷管理
例子:
docker run -d nginx:latest #啟動nginx這個容器
docker ps #查看剛啟動的容器的ID或名字
docker exec -it 容器的名字或ID /bin/bash #進入容器里的bash控制終端
nginx的docker容器里操作:
ls /usr/share/nginx/html #一般猜測這個網上的容器的nginx目錄會在鏡像系統里的/usr/share/nginx/html
echo ‘hehe’>/usr/share/nginx/html/index.html #將index.html主頁的內容改為hehe,在外部宿主機可curl這個容器的IP地址查看內容是否更改。
宿主機操作:
docker inspect 容器的ID|grep -i ipaddr #在宿主機外部使用docker命令的inspect過濾獲取容器里的ip元數據。
curl nginx容器的IP #可查看內容是否更改。
問題:此時想讓容器里的nginx網站根目錄使用的是宿主機外部的數據目錄怎么操作呢?難道要傳進去嗎?下面會使用docker的掛載方法,將本機的目錄數據掛載到容器里的某個目錄,這樣就能讓容器能放我們的內容了。
數據卷(文件或目錄)
-v /data #這是我們宿主機存放web數據的目錄位置,如果宿主機沒有data目錄,docker使用命令時會自動幫忙創建。
-v src:dst #-v參數,src是外部宿主機的掛載位置地址,dst是docker鏡像容器的掛載位置地址。
docker run -d --name nginx -p 80:80 -v /data:/usr/share/nginx/html nginx:latest #啟動nginx鏡像容器,並且指定端口映射,將本機的80端口映射到容器里的80端口,並且掛載我本機的data目錄到nginx容器里的/usr/share/nginx/html 目錄。
echo ‘oldboy’ >index.html #寫一個主頁文件測試。
在物理機瀏覽器訪問:
http://10.0.0.7 #一訪問宿主機的IP就能訪問到容器里的80端口,里面掛載的目錄內容也能成功訪問。
說明:以后要更新內容,就直接在宿主機的/data目錄就能這樣更改,以后更新代碼就方便好多。
數據卷容器(復制以掛載好目錄的容器)
--volumes-from #復制已指定好掛載源地址和目標地址的容器名字就可實現復制他的參數(相當於掛載跟他一模一樣)
docker run -d --name nginx2 -p 81:80 --volume nginx:latest #新開啟一個nginx容器,命名為nginx2,指定端口不跟上面操作沖突,並且使用vlomue參數指定上一個nginx容器的掛載參數,使掛載參數一模一樣。
說明:如果使用集群的話,這個參數會非常方便,只需啟動nginx鏡像容器時只需使用--volumes參數就能實現每台nginx的所有代碼都更新在宿主機的一個目錄里。
1.20 手動制作docker鏡像
例子:
docker run -it -p 1122:22 guyton/centos6 /bin/bash #將容器里的22端口映射到宿主機的1122端口,用的鏡像是guyton/centos6,並且進入bash控制台。
cat /etc/redhat-release #容器里查看系統版本信息,一看是Centos6.9的,一看就是小型的Centos6系統集成的鏡像。
yum install -y openssh-server #安裝一個ssh服務
/etc/init.d/sshd start #啟動sshd服務,並且在/etc/ssh下生成dsa格式的公鑰和私鑰,rsa的公鑰和私鑰,這就是docker啟動ssh服務時,ssh啟動腳本在后台做的一些事情。
netstat -lntup #檢查22端口是否啟動
讓鏡像就單啟動ssh服務就夯住的方法:
/usr/sbin/sshd -D #在進入Centos6的容器里的bash控制端在執行這個命令,啟動ssh服務時,后面加上大寫-D就能讓他夯住,作用跟進入bash命令類似,單啟動sshd夯住就行。
說明:我想讓下次去到一個新地方時,那就可以將這些重復的yum下載與初始化做成一個鏡像,我直接docker run啟動這個ssh的鏡像容器就能用,非常方便,不用那么多繁瑣的操作。
制作鏡像
docker commit keen_lichterman centos6-ssh #復制剛才yum install好的初始化環境的容器,啟動狀態不保存,只保存文件在容器里,新建一個容器名字為centos6-ssh
docker images #查看目前已有的鏡像,看到有剛創建好的centos6-ssh的新鏡像
docker run -p 2122::22 -d centos6-ssh /usr/sbin/sshd -D #啟動剛創建好的鏡像,指定本地2122端口映射為容器里的22端口,並且讓他指定第一個命令為/usr/sbin/sshd -D,第一個命令相當於第一個進程,他夯住了,就持續運行不會退出了。
docker -ps #查看剛啟動的centos6-ssh鏡像是否卡着/usr/sbin/ssh這個進程持續運行。
宿主機里操作:
ssh root@10.0.0.11 -p 2122 #連接宿主機的2122端口,相當於連接容器里的22端口,輸入密碼也是輸入容器里密碼。
1.21 Docker啟動容器時,既啟動httpd又啟動sshd(雙服務)的方法
說明:以上操作,(啟動docker對第一個進程夯住)都是對單個服務啟動后給它夯住持續運行,但容器里有兩個服務,讓兩個服務同時運行並夯住又是個問題,前面學了ssh的-D前台夯住的方法,但httpd夯住的方法還不知曉,所以這里就有一個另類實現方法,寫一個腳本來並行執行,讓ssh服務斷后來夯住,這樣就實現前面服務可不夯住,后面有人斷后夯住的方法。
步驟一:先做好一個初始化鏡像容器,將所有要下載和執行腳本的操作都做好,隨后在克隆成新的,讓后面人一次性啟動。
docker run -it --name test centos6-ssh /bin/bash #啟動一個容器,容器名字待會在docker ps里叫test,容器是創建好ssh容器,里面有ssh服務,並且運行一個bash控制台。
rpm -qa|grep openssh #檢查之前yum的ssh在不在。
ps -ef #檢查進程運行狀態,剛啟動一個新的鏡像容器時,他上一次正在執行的ssh等其他服務運行狀態是不保持的,保持的容器里面的文件,例如服務的配置文件、網站根目錄數據等。
yum install -y httpd #下載一個apache,安裝包比較小,可使用這個來測試。
vi init.sh #在根目錄下創建一個腳本為init.sh,填上以下內容。
#!/bin/bash
/etc/init.d/httpd start #啟動httpd的命令填上去
/usr/sbin/sshd -D #啟動sshd並且夯住的命令在最后填寫(注意一定要在最后,優先順序特別重要!)
chmod +x init.sh #最后給init.sh腳本加上執行權限,否在docker那運行不起來,否則加 /bin/bash /init.sh來無x權限執行。
ctrl+p 松開 ctrl+q #臨時退出一下,先讓他暫時運行着。
步驟二:宿主機上操作,復制剛初始化的鏡像容器,另存為一個新鏡像容器名字
宿主機上操作:
docker ps #查看剛才初始化好的並且正在后台運行的容器名字與ID
docker commit test centos6-httpd #復制鏡像,剛才運行的鏡像容器在docker ps里是叫test的,所以指定test這個容器,並且另存為一個新的鏡像名字。
docker images #查看已有的鏡像容器
docker run -d --name centos6-httpd -p 3022:22 -p 80:80 centos-httpd:latest /init.sh #運行剛創建的centos6-httpd容器,因待會要測試用,所以端口映射,本機的3022端口指向容器的22端口,本機的80端口指向容器的80端口,使用鏡像是使用本倉庫默認的版本,並且容器第一個執行的進程是/init.sh,他會並行執行最后夯住,一定要加/斜號,告訴他腳本位置並執行。
docker ps #查看剛啟動的鏡像的ID或名字,看到已經啟動,並且用init.d腳本掛載夯住正常運行了。
步驟三:使用物理機訪問剛制作好的新鏡像。
物理機訪問瀏覽器測試:
http://10.0.0.7
ssh root@10.0.0.7 -p 3022 #連接后,可使用ps -ef查看進入容器里面的進程,可以看到先啟動的是init這個腳本,后面是apache默認參數啟動的多個work線程,這種情況輸入正常情況,因apache還沒改配置文件,所以默認啟動多個work進程,最后ssh連接也有一個ssh進程,最后有一個ssh來夯住。
1.22 dockerfile自動構建docker鏡像(創建一個鏡像)
重要說明:需要提前准備好rootfs.tar.xz文件,否則無法完成以下操作,docker的常用的子系統rootfs。
rootfs下載地址:https://mirrors.tuna.tsinghua.edu.cn/lxc-images/images/ubuntu/trusty/amd64/default/20180824_07%3A43/
說明:這個網址是從學習視頻里發現的,比較好運,否則還找不到,如報錯404找不到,那就到https://mirrors.tuna.tsinghua.edu.cn/lxc-images/images/ubuntu/trusty/amd64/default/ 下去找最新版本的目錄進去找rootfs.tar.xz下載。
dockerfile主要組成部分:
基礎鏡像信息
維護者信息
鏡像操作指令
容器啟動時執行指令
dockerfile常用指令:
FROM 這個鏡像的媽媽是誰?(指定基礎鏡像)
MAINTAINER 告訴別人,誰負責養它?
RUN 你想讓它干啥(在命令前面加上RUN即可)
ADD 給它點創業資金(COPY文件,會自動解壓)
WORKDIR 我是cd,今天剛化了妝(設置當前工作目錄)
VOLUME
EXPOSE (對外暴露的端口,一般配合-P 啟動容器隨機端口使用,后查看容器隨機端口對應的是哪個端口,來給用戶連接)
CMD 容器啟動時候默認執行的命令
操作步驟:
環境硬性准備工作:
cd /opt/
mkdir centos6-base
cd centos6-base/ #將rootfs.tar.xz文件放到目錄下,后面需要解壓並且生成一個小型的系統,rootfs.tar.xz是docker的前身系統,前提得准備好rootfs.tar.xz文件才能做,是根據lcx系統文件里面的rootfs.tar.xz文件做的,需要找到他,否則做不了。
填寫硬性配置文件:
vim Dockerfile #新建一個Dockerfile文件,官方格式名字就叫這個,最好不要更改,保持規范就好,一定要在centos6-base目錄下新建。
FROM scratch #做最基礎鏡像時,最好填寫scratch白手起家的意思,從誰的基礎上開始做這個小型系統,類似導入一個鏡像,從這個鏡像繼續操作,如果沒有鏡像,那不以任何鏡像為基礎,寫法就為:FROM scratch,同時說明接下來所寫的指令將作為鏡像的第一層開始,相當於它是在自己作鏡像。
ADD rootfs.tar.xz / #添加一個文件,ADD這個功能能自動解壓這個文件,並且能制定解壓后的位置,在鏡像的/根目錄下。
CMD [“/bin/bash”] #容器啟動時,默認執行的命令,啟動/bin/bash
開始制作鏡像:
docker image build -t centos6-base . #使用build -t命令指定制作完后的鏡像名字為centos6-base,並且指定Dockerfile文件的位置,那個點.是在當前目錄下,因為剛進入了centos6-base目錄下,所以文件也在那,命令在當前目錄下執行的,也可寫文件絕對路徑。
docker images #查看制作好的鏡像,並且找到centos6-bash的鏡像名字。
進入制作好的鏡像:
docker -run -it --name oldboy-base centos6-base:latest #dockerfile制作鏡像前在cmd指定了默認啟動后執行的命令在/bin/bash,否則沒有指定cmd就會報錯啟動不了。
說明:以上操作都只是做一個最最基礎的bash鏡像,相當於用centos或Ubuntu的底層系統來做的一個小系統。
鏡像后加latest的原因:加了latest是使用當前倉庫默認的辦法,也可以指定最新的版本,也有一些小區別,相當於使用當前版本還是使用最新版本的區別。
使用dockerfile制作應用場景服務的鏡像,不在是基礎系統鏡像,而是有服務的鏡像:
說明:當給人家一個鏡像的時候可能要1個G,但讓他使用我的dockerfile文件制作鏡像時,會非常快,並且傳輸非常方便,不用發上G的文件,最小幾十M。
操作步驟:
環境硬性准備工作:
mkdir centos6-ssh
cd /otp/centos6-ssh
容器的啟動腳本配置文件:
vim init.sh #在/opt/centos6-ssh目錄里編寫啟動腳本。
#!/bin/bash
echo 123456|passwd --stdin root #因鏡像容器要開啟ssh服務,如果容器里沒有密碼,有ssh也連接不上,這里給機器賦予一個密碼。
/etc/init.d/httpd start #啟動好httpd服務
/etc/init.d/sshd start #重點:要啟動一次sshd后會生成公鑰私鑰對,否則不啟動一次來生成,會啟動容器時會報錯。
tail -f /var/log/httpd/access_log #重點:可不使用/usr/sbin/sshd -D來夯住,可使用tail 命令持續查看httpd的日志,前提知道日志路徑,不要瞎猜。
填寫硬性配置文件:
vim dockerfile
FROM scratch #白手起家,表示自己個人制作基礎鏡像文件。
ADD rootfs.tar.xz / #添加一個文件,將根目錄下的rootfs.tar.xz文件解壓到容器里的/根目錄下
RUN yum install openssh-server httpd -y #在構建鏡像時要執行的命令,相當於還未執行鏡像前要做的初始化操作的命令。
ADD init.sh /init.sh #添加一個文件,將dockerfile目錄下的init.sh啟動腳本,拷貝到容器里的/根目錄下,里面寫好了要操作什么和夯住的命令。
CMD ["/bin/bash","/init.sh"] #啟動鏡像時默認執行的命令,執行/bin/bash並且拼接再執行容器里的/init.sh腳本,幫助啟動服務和初始化服務。
開始制作鏡像:
docker build -t centos-ssh-httpd . #build -t制作一個鏡像,新制作的鏡像名字為centos-ssh-httpd,這個點並且指定dockerfile文件的位置,可寫全路徑。
重點:因上面操作已經制作過一次FROM scratch等操作了,這就會做為docker的一個緩存,重新制作鏡像時,做過的操作會快速執行,沒做過的就會等一會。
重點2:剛到工作生產環境中,制作鏡像名字一定要docker images查看已有的鏡像名字,否則重復之前鏡像名字會頂替掉原來的,並且原來的鏡像名字會出現為空,這樣會不知道哪個鏡像是哪個鏡像,就亂套了。
進入制作好的容器:
docker run -d -p 80:80 -p 1022:22 centos-ssh-httpd #運行剛制作好的容器,指定映射端口,本地的80端口指向容器的80端口,本地的1022端口指向容器的22端口,后面如果指定了運行容器要執行的命令就會替換掉dockerfile構建時cmd的命令,之前的服務都沒啟動,這是重點。
測試服務是否正常:
http://10.0.0.7
ssh root@10.0.0.7 -p1022
說明:填寫dockerfile文件時,ADD就像開頭,CMD相當於結尾,他們中間寫的就是構建的命令,比如ADD添加完了文件,然后寫一些其他操作,寫入文件修改文件等的命令,到了CMD相當於后面要執行的操作,執行腳本等,類似於ansible寫playbook劇本類似原理。
1.23 docker引用傳參方式指定每次登陸容器的登陸密碼
說明:當使用dockerfile創建一個鏡像時,他的密碼一般都被指定為一個固定的密碼,例如echo 123|passwd --stdin root 這樣的方式,每當使用鏡像時都輸入這個統一的密碼,當公司有人要離職后,如果密碼不更改,離職的員工泄露讀獨自登陸docker容器的ssh做事情,那就非常麻煩,數據不安全,所以要使用init.sh起始腳本設置初始化密碼要使用變量方式來傳參,(達到每次使用容器就指定不同的密碼)讓容器、數據變安全!
步驟一:找到容器第一個啟動腳本,指定每次的登陸密碼由管理人員隨時傳參控制
vim init.sh
#!/bin/bash
echo $ssh_pwd|passwd --stdin root #bash腳本里指定一個$ssh_pwd變量,設置這個是容器系統里的一個全局變量,讓用戶在外指定變量值是多少傳遞進來。
/etc/init.d/httpd start
/etc/init.d/sshd start
tail -f /var/log/httpd/access_log
步驟二:啟動docker時指定docker容器系統里的密碼,讓用戶連接時每次都能設置不同的密碼。
docker run -d -p 82:80 -p 5022:22 -e “ssh_pass=12345678” centos-ssh-plus #啟動docker時使用-e參數指定好ssh_pass變量的值為12345678,然后在啟動init.sh的腳本,值就有了。
說明:使用ssh連接方式登陸到這個容器里去查看剛才登陸容器賦值ssh_pwd的值是看不到環境變量有ssh_pwd的,必須得登陸到docker原來容器的bash環境下才能查看的到環境變量。
應用場景
類似於實驗樓,給你虛擬化一個環境來做實驗,基本就是一個docker容器里的一個小型linux系統,開一個實驗頁面相當於一個顯示出隨機密碼的docker信息發到頁面給用戶登陸,並且會定時會清理docker容器,只有充錢才能變讓docker系統變得持久。
應用場景2
類似於實驗樓,能做更多IP與主機信息與業務nginx上,做一個變量設置,這樣就能用戶用我們的docker,就能告知用戶指定什么變量是修改什么,或修改業務中自己的信息,從而實現更多制定化docker,快速准備業務。
個人理解dockerfile
dockerfile文件只收集類似shell 過程改變的記錄,給人家執行這些操作來自動下載自動改變,和設置我們指定的參數,就需啟動按照我們給用戶的說明來設置啟動。
dockerfile可道雲小項目實驗
說明:每一個項目最好為一個文件夾,例如nginx,就在/opt/dockerfile/nginx目錄下新建dockerfile文件來編排構建
說明2:此處我使用的是本地源為下載源,源地址主要區分好系統是6或7,可去清華園,163源去替換以下源地址。
2、項目目錄下腳本,名為init.sh
3、開始構建制作docker鏡像
docker image build -t centos_testv2 .#制作后的鏡像名為centos_testv2,dockerfile文件在本目錄,所以填寫.
4、啟動剛制作的docker鏡像,並指定映射端口
docker run -d -p 8080:80 -p 8022:22 centos_testv2 #-p指定兩個httpd與ssh端口映射。
5、查看最后一個啟動的容器是否夯住啟動成功
docker ps -l
docker常用項目鏡像下載地址
http://docs.docker.com/samples/library/
1.24 docker鏡像的分層(dockerfile構建快慢,緩存原理)
說明:鏡像的分層類似於虛擬機的鏈接克隆,當你有一個模板鏡像時,你在去克隆一個docker容器,會非常快,是因為他已經有存儲的文件,99%每個系統文件都一樣,只有一小部分是改變層,所以比較快,不像VM虛擬機的完整克隆一樣完整克隆過來非常慢。
1.24.1 docker鏡像分層原理圖
說明:每克隆一個鏡像,他的系統最底層base rootfs是不會變的,因為以這個為基礎,這是第一層,第二層於dockerfile里的第二步改變了什么,加了什么,如果沒有改變,就很快的克隆,如果有改變,當克隆第二個鏡像時,他會從模板的改變層(改變1)后面延伸給第二個鏡像繼續往下重新構建一個鏡像系統,這樣就會時間有點長,相當於克隆鏡像的原理,他們變化的流程,快速復制的原理。
小總結:沒改變的層就繼續復制,改變的層就會從那一層從外延伸新的層,后面所有層就重新構建了,相當於重新構建而不是復制已有的了,因為他的改變層不是跟之前模板是有關系的了,相當於父親變了,就重新延伸發展了,每一層都相當有固定ID的,他的ID就是他的sha256,當改變層跟之前模板的sha256的ID不同了,就相當於找不到他爹了,找不到他父親了,所以就會重新延伸發展新的,就相當於重新來花時間構建了。
說明2:這就是為什么dockerfile加了一行就重新構建這么慢了,人家構建怎么這么快呢的原因,懂了這個原理,以后再構建鏡像時只要想快速構建,就要盡可能的改最往后的一行,到最后一步改變了構建也會很快。
1.25 docker多個容器進行網絡連通(zabbix、mysql、web)
docker的理念來推薦一個容器只運行一個服務,不然一個容器死了,整個架構就死了,但一個服務里有很多個組件配合起來才能成為一個架構體系,所以就要讓每個docker容器進行連通通信來交互成為一個架構。
zabbix官方使用參數配合連通的例子:
步驟一:將所有包裝應用服務的鏡像導入到宿主機里,這里舉例將zabbix所有組合套件拉進來(zabbix官網下載鏡像)
docker pull mysql/mysql-server #未指定版本,默認pull下載最新版本。
docker pull zabbix/zabbix-server-mysql
docker pull zabbix/zabbix-web-nginx-mysql
docker pull zabbix/zabbix-java-gateway
說明:有個小規律,是zabbix里的鏡像,就必須在包的前面加上zabbix,是mysql的包就前面加上mysql
步驟二:將剛才下載好的鏡像進行指定參數來啟動,(並指定環境變量參數做好連通)
mysql鏡像啟動
# docker run --name mysql-server -t \
-e MYSQL_DATABASE="zabbix" \ #每個都是變量,設置變量值等於誰,然后其他腳本都是已經設置好變量來接收了。
-e MYSQL_USER="zabbix" \
-e MYSQL_PASSWORD="zabbix_pwd" \
-e MYSQL_ROOT_PASSWORD="root_pwd" \
-d mysql:5.7 \ #此處指定mysql5.7版本,因上面pull的mysql未指定版本,所以pull時自動裝最新版本,跟這不匹配,所以重新下載5.7版本。
--character-set-server=utf8 --collation-server=utf8_bin #最后指定字符集
java-gateway鏡像啟動
# docker run --name zabbix-java-gateway -t \
-d zabbix/zabbix-java-gateway:latest
zabbix-server-mysql鏡像啟動
# docker run --name zabbix-server-mysql -t \
-e DB_SERVER_HOST="mysql-server" \
-e MYSQL_DATABASE="zabbix" \
-e MYSQL_USER="zabbix" \
-e MYSQL_PASSWORD="zabbix_pwd" \
-e MYSQL_ROOT_PASSWORD="root_pwd" \
-e ZBX_JAVAGATEWAY="zabbix-java-gateway" \
--link mysql-server:mysql \
--link zabbix-java-gateway:zabbix-java-gateway \
-p 10051:10051 \
-d zabbix/zabbix-server-mysql:latest
zabbix-web-nginx-mysql鏡像啟動
# docker run --name zabbix-web-nginx-mysql -t \
-e DB_SERVER_HOST="mysql-server" \
-e MYSQL_DATABASE="zabbix" \
-e MYSQL_USER="zabbix" \
-e MYSQL_PASSWORD="zabbix_pwd" \
-e MYSQL_ROOT_PASSWORD="root_pwd" \
--link mysql-server:mysql \
--link zabbix-server-mysql:zabbix-server \
-p 80:80 \
-d zabbix/zabbix-web-nginx-mysql:latest
說明:以上所有操作最好關閉其他占用80端口,3306端口否則啟動不了docker里面指定的端口,會報錯,提示占用。
步驟三:在zabbix客戶端機器安裝zabbix-agent進行與zabbix服務端進行連接接受控制。
https://mirrors.tuna.tsinghua.edu.cn/zabbix/zabbix/3.2/rhel/7/x86_64/ #按照zabbix的版本下載客戶端agent的版本,配置文件填寫zabbix服務端的宿主機IP。
1.26 docker搭建私有倉庫
說明:搭建非常簡單,只需要下載registry鏡像再啟動就可以。
docker pull registry #下載registry鏡像
docker run -d -p 5000:5000 --restart=always --name registry -v /opt/myregistry:/var/lib/registry registry #當docker服務重啟時,這個鏡像會自動重啟,這是--restart=always參數的作用,並且-v將本地的/opt/myregistry的目錄掛載到容器里的/var/lib/registry目錄。
docker ps #可找到registry這個容器已經啟動了。
docker image tag docker.io/centos6-base 10.0.0.7:5000/oldboy/centos6-base #給現有的Centos6-base鏡像定義一個標簽,指定現有鏡像,鏡像都在docker.iot目錄,最后指定tag標簽的名字,此處加上倉庫地址比較好記憶,如果沒有就加上其他鏡像。
docker images #此時可看到創建好的鏡像標簽id與現有的centos6-base的id一模一樣,相當於使用同一個鏡像而已。
docker push 10.0.0.7:5000/oldboy/centos6-base #這里使用push推送到docker的默認倉庫目錄里,此處會報錯一個錯誤,版本更新過后只能使用https,這可以解決。
解決倉庫https方法:
vim /etc/docker/daemon.json #編輯docker的某個配置文件
{
"registry-mirrors": ["https://r1ztx9gb.mirror.aliyuncs.com"], #注意后面有個逗號,json的配置文件的格式都是這樣,加一行內容。
"insecure-registries": ["10.0.0.7:5000"] #寫上這個內容注意中文字符,逗號符號問題,寫上docker的倉庫地址,使其推送這個地址時,使用http方式推。
}
重點說明:文件不能有多余空格,也不能多一行,否則出錯,可使用cat -A 查看。
systemctl restart docker #重啟docker服務
docker ps #查看registry服務是否正常運行狀態,並且端口沒有占用5000端口,因為加了參數所以重啟docker服務會自動重啟registry容器
docker push 10.0.0.7:5000/oldboy/alpine #重新push這個alpine的鏡像應該就可以了。
在其他docker機器上要使用內網私有倉庫的操作步驟: (需要使用私有倉庫地址的機器上操作)
vim /etc/docker/daemon.json #編輯使用倉庫的客戶端的daemon配置文件,寫入以下內容,內容作用是下載加速
{
"registry-mirrors": ["https://r1ztx9gb.mirror.aliyuncs.com"],
"insecure-registries":["10.0.0.7:5000"]
}
systemctl restart docker #重啟docker生效。
docker pull 10.0.0.7:5000/oldboy/alpine #下載docker服務端倉庫里的alpine應該就成功了。
docker images #可查看現有的鏡像,已經有了剛下載的alpine
curl http://10.0.0.7:5000/v2/_catalog #通過curl命令查看docker倉庫里是否已經添加成功了鏡像在里面的方法。
{"repositories":["oldboy/alpine"]} #這里已經有了,這是完整的鏡像路徑地址。
1.26.1 docker搭建私有倉庫的密碼認證
說明:當私有倉庫的地址被外面的人知道后,可以隨意下載你的容器鏡像,並且可以看到容器里面的資料然后泄露資料,並且可以上傳一大堆后門的鏡像來反彈nc做一些其他后門就非常危險,所以要給倉庫鎖上一個認證,誰要用我的倉庫就必須要給密碼,才能進行下載和上傳。
mkdir /opt/registry-var/auth/ -p
yum install httpd-tools.x86_64 -y
htpasswd -Bbn oldboy 123456 >>/opt/registry-var/auth/htpasswd #添加一個認證用戶和密碼,生成為一個倉庫里的一個認證文件暫時放着,密碼是密文加密的。
docker run -d -p 5000:5000 -v /opt/registry-var/auth/:/auth/ -e "REGISTRY_AUTH=htpasswd" -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd registry #掛載剛才生成的認證文件到容器里的/auth里,然后設置一些環境變量。
記得把沖突解決,有端口沖突。 #不知是否要kill掉5000正在啟動的容器,在重新啟動容器,因為修改了5000容器的文件。
1.27 docker個人理解總結
docker與k8s或kvm一樣的原理,都相當於命令行、進程式的虛擬機而已,docker特點都是快,占用內存比較小一些,命令行操作掛載等技術,非常方便又兼容強大。
1.27.1 Docker故障報錯
故障一:
[root@oldboyedu-47 docker]# docker run -p 80:80 NGINX
/usr/bin/docker-current: Error parsing reference: "NGINX" is not a valid repository/tag: repository name must be lowercase.
See '/usr/bin/docker-current run --help'.
說明:這是沒有啟動nginx所造成的。
故障二:

說明:因為沒有在國內找到最新版本的docker鏡像,所以就默認去國外去找docker鏡像了,但是國內網去國外下載就下載不了,這里顯示超時了,
這里推薦國外加速器來進行下載:阿里雲加速器,daocloud加速器,中科大加速器。
1.28 Docker常用命令思維導圖總結