1.在軟體開發中,最麻煩的事情之一就是環境設定。在正常情況下,如果要保證程式能執行,我們需要設定好作業系統,以及各種庫和元件的安裝。
2.舉例來說,要執行一個Python程式,計算機必須要有 Python 引擎,還需要安裝好程式的各種依賴,甚至還要設定特定的環境變數。假設你有兩個程式都需要部署在同一個伺服器上,一個需要軟體是基於Python2.0,一個是Python3.0,那麼在部署上就很容易造成混亂。因為不同版本的Python模組可能互不相容,況且不同開發環境上的庫也需要額外的設定。如果要部署很多程式,而開發環境和部署環境各不相同的話,可想而知設定得多麼麻煩。
3.為了更好地將軟體從一個環境移植到另一個環境上,必須從根源上解決問題,那麼如何在移植軟體的時候,將一模一樣的原始環境遷移過來呢?
虛擬機器器是移植環境的一種解決方案。虛擬機器器本質上也是一個軟體,在這個軟體中,我們可以執行另一種作業系統。比如我們想要在 MacOS 上執行 Linux 系統,我們就在電腦上安裝 Linux 映象,並使用虛擬機器器開啟此映象,就能建立出一個鏡中鏡了。這個方案非常方便,想要新環境,就安裝映象,然後使用虛擬機器器開啟,不想要直接刪除。但是這個方案有幾個缺點:
為了解決虛擬機器器存在的這些缺點,Linux發展出了另一種虛擬化的技術:Linux容器。Linux 容器不是模擬一個完整的作業系統,而是對程序進行隔離。或者說,就是在正常程序的外面套用了一個保護層。對於容器裡面的程序來說,它接觸到的各種資源都是虛擬的,從而實現與底層程式的隔離。由於容器是程序級別的,相比虛擬機器器有更多優勢:
Docker屬於Linux容器的一種封裝,提供簡單易用的容器使用介面,它也是目前最流行的Linux容器解決方案。Docker 將軟體程式碼和其依賴,全打包在一個檔案中。執行單個檔案,就會生成虛擬容器。在這個虛擬容器中,不管原生的作業系統是如何的不同,此容器都能照常執行。
簡而言之,Docker的介面非常簡單,可以幫助使用者更好地建立和使用容器,讓相同的程式碼在不同的環境上正常執行。
Docker容器和傳統VM技術,在技術實現上有所不同。下圖顯示的是VM與Docker容器的邏輯組成:
Server:相當於雲伺服器
Host OS:為作業系統
Docker Engine:可以認為我們在這個作業系統上安裝了一個docker的軟體
App A:在Docker元件中執行App A
App B:在Docker元件中執行App B
# 所以docker完全沒有作業系統的概念,用的還是宿主機的作業系統,但是它做出了隔離。也實現了虛擬化。
虛擬機器器與Docker容器對比
Docker容器的執行邏輯如下圖所示,Docker使用使用者端/伺服器 (C/S) 架構模式,Docker守護行程(Docker daemon)作為Server端接收Docker使用者端的請求,並負責建立、執行和分發Docker容器。Docker守護行程一般在Docker主機後臺執行,使用者使用Docker使用者端直接跟Docker守護行程進行資訊互動。
其中:
Docker是一個使用者端-伺服器端(C/S)架構程式,Docker使用者端只需要向Docker伺服器或者守護行程傳送請求即可,伺服器或者守護行程將完成所有工作並返回結果,Docker提供了一個命令列工具以及一正太Restful Api,我們可以在同一臺宿主機上執行Docker守護行程和使用者端,也可以從本地Docker使用者端連線執行在另外一臺宿主機的Docker的守護行程。
# 使用了RESTful API的目的就是為了統一規範,無需自己在生成一套體系。現在幾乎所有的軟體都是通過RESTful API來傳輸資料。
1.有了映象---》映象執行起來是容器(真正的執行單位)
映象 : 物件導向的類
容器 : 物件
2. 映象是從哪裡來的?
-映象就是一堆檔案
-從遠端倉庫獲取(拉取)
Docker是一個使用者端-伺服器(C/S)架構程式(mysql,redis都是cs架構),整套RESTful API
•Docker使用者端(Docker Client)是使用者與Docker進行互動的最主要方式。當在終端輸入docker命令時,對應的就會在伺服器端產生對應的作用,並把結果返回給使用者端。Docker Client除了連線本地伺服器端,通過更改或指定DOCKER_HOST連線遠端伺服器端。
•Docker Daemon其實就是Docker 的伺服器端。它負責監聽Docker API請求(如Docker Client)並管理Docker物件(Docker Objects),如映象、容器、網路、資料卷等
•俗稱Docker倉庫,專門用於儲存映象的雲服務環境.
•Docker Hub就是一個公有的存放映象的地方,類似Github儲存程式碼檔案。同樣的也可以類似Github那樣搭建私有的倉庫。
•映象:一個Docker的可執行檔案,其中包括執行應用程式所需的所有程式碼內容、依賴庫、環境變數和組態檔等。
•容器:映象被執行起來後的範例。
•網路:外部或者容器間如何互相存取的網路方式,如host模式、bridge模式。
•資料卷:容器與宿主機之間、容器與容器之間共用儲存方式,類似虛擬機器器與主機之間的共用檔案目錄。
docker pull : 拉取映象(從遠端倉庫中獲取放到Images)
docker run : 執行映象(執行映象後就會放到容器裡)
docker container : 檢視執行了那些映象(容器)
docker image : 檢視有那些映象
docker network : 檢視網路
docker valume : 檢視資料表等
- 資料表等建議放到宿主機上,因為如果一旦容器刪除了,在容器上的資料表就沒有了。
1.映象:就是一個唯讀的模板,映象可以用來建立docker容器,一個映象可以建立很多容器
2.容器:用映象建立的範例,可以被啟動、開始、停止、刪除。每個容器都是相互隔離的、保證安全的平臺。可以把容器看做是一個簡易版的Linux環境(包括root使用者許可權、程序空間、網路空間等)和執行在其中的應用程式。容器與映象的關係類似於物件導向程式設計中的類和物件,映象好比是類,那麼容器則是物件
3.倉庫是集中存放映象檔案的場所。倉庫(repository)和倉庫註冊伺服器(Registry)是有區別的。倉庫註冊伺服器上往往存放多個倉庫,每個倉庫中又包含了多個映象,每個映象有不同的標籤(tag)。倉庫又分為公開倉庫(public)和私有倉庫(private)兩種形式。最大的倉庫是DockerHub (https://hub.docker.com),存放了數量龐大的映象供使用者下載。國內的公有倉庫包括阿里雲、網易雲等。
docker本身就是一個容器執行載體或稱之為管理引擎。我們把應用程式和設定依賴打包好形成一個可交付的執行環境,這個打包好的執行環境就似乎image映象檔案。只有通過映象檔案才能生成docker容器。image檔案可以看做是容器的模板。docker根據image檔案生成容器範例。同一個image檔案,可以生成多個可以同時執行的容器範例。
image檔案 生成的容器範例,本身也是一個檔案,稱為映象檔案
一個容器執行一種服務,當我們需要的時候,就可以通過docker使用者端建立一個對應的執行範例,也就是我們的容器。
倉庫就是放了一堆映象的地方,我們可以把映象釋出到倉庫中,需要的時候從倉庫中拉下來就可以
1 windows安裝(不建議你裝)http://get.daocloud.io/
# 0 解除安裝
sudo apt-get remove docker docker-engine docker.io containerd runc
# 1 安裝必要工具
sudo apt-get update
sudo apt-get install \
apt-transport-https \
ca-certificates \
curl \
gnupg-agent \
software-properties-common
# 2 安裝GPG證書
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
#換成阿里雲
curl -fsSL http://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo apt-key add -
# 2 寫入軟體源資訊
#官方
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
#換成阿里雲
sudo add-apt-repository "deb [arch=amd64] http://mirrors.aliyun.com/docker-ce/linux/ubuntu $(lsb_release -cs) stable"
# 3 更新並安裝docker-ce
sudo apt-get -y install docker-ce
# 4 開啟docker服務
systemctl status docker
# 安裝成功後,使用 docker version檢視
如果出現許可權禁止,需要切換到root使用者執行
su
輸入密碼
docker version
0 解除安裝(如果沒有安裝過無需解除安裝)
yum remove docker docker-common docker-selinux docker-engine
rm -rf /var/lib/docker
1 更新yum
yum update
2 安裝需要的軟體包:yum-util (會生成該命令yum-config-manager)
命令:yum install -y yum-utils device-mapper-persistent-data lvm2
3 執行(向你的yum源,增加一條記錄)
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
4 安裝
yum install docker-ce
5 驗證安裝(檢視版本)
docker -v
~]# docker -v (19年03月12日釋出)
# 自從分了docker-ce和docker-ee以後,以年份命名版本
Docker version 19.03.12, build 48a66213fe
注意:自從區分docker-ce和docker-ee之後,docker最初始的版本是17.03,也就是17年釋出的,所有17是老版本和新版本的分水嶺
6 啟動docker服務
systemctl start docker
7 停止docker服務,重啟docker服務
systemctl stop docker
systemctl restart docker
8 開機啟動
systemctl enable docker
9 檢視概要資訊
docker info(你可能寫了一個管理docker的運維平臺)
下載映象:
# 遠端倉庫地址:https://hub.docker.com/
- 註冊 登入
# 你可以上傳映象(類似於github),你把你製作的映象傳上去,別人可以下載使用
# 搜尋映象:
方式一:https://hub.docker.com/ 點點點搜尋
方式二:docker search 映象名字
# 後面有OK代表官方
# search作用:
搜尋Docker Hub(映象倉庫)上的映象
# 命令格式:
docker search [OPTIONS] TERM
# 命令引數(OPTIONS):
-f, --filter filter 根據提供的格式篩選結果
--format string 利用Go語言的format格式化輸出結果
--limit int 展示最大的結果數,預設25個
--no-trunc 內容全部顯示
# 命令演示
docker search -f is-offical=true ubuntu
docker search ubuntu
# 拉取下載映象
docker pull hello-world # 最新版本latest
docker pull hello-world:nanoserver # 指定版本
docker pull hello-world:版本號(預設最新,可以指定版本號)
檢視映象
# 檢視機器上有哪些映象
# 命令:docker images
# 解釋:
REPOSITORY TAG IMAGE ID CREATED SIZE
映象名字 版本 id號 建立時間 大小
執行映象
# 命令:
docker run 映象名字
docker run hello-world
# 例:
第一個hello-world(沒有任何意義)
docker run hello-world
1 使用者端連到伺服器端,服務下載了hello-world映象
2 通過映象跑起容器來
3 容器輸出一些東西,通過伺服器端傳送給使用者端,使用者端展示在視窗裡了
刪除映象
# 命令:
docker rmi 映象名字/Id號
# 注意:
1.如果還有基於這個映象的容器,是不允許刪除映象的
2.可以先刪除容器,在刪除映象
# 查詢容器依賴
docker ps -a
# 在刪除要不允許的映象
docker rm 容器/id
# 拉取python3.6映象,redis最新映象,mysql5.7映象
docker pull python:3.8
docker pull redis
docker pull mysql:5.7
docker pull nginx
docker pull centos:centos7
# 查詢當前映象
docker images
映象容器是可以看作:
-映象就是一堆檔案,這堆檔案通過docker跑起來,就是容器,你現在就把他當成,一個作業系統內跑了這個軟體(比如就是:centos+redis)
-假設centos7的映象跑起來,此時容器你就當成在你宿主機上跑了一個centos7的作業系統(虛擬機器器)
1 刪除容器
docker rm 容器名字/容器id
2 啟動並執行容器
# 通過centos:centos7映象,建立一個容器名字叫mycentos,並且把它執行起來
docker run -di --name=mycentos centos:centos7
# 結果:會列印出容器的id號
3 檢視機器上正在執行的容器
docker ps
4 檢視宿主機上所有的容器(包括停止的)
docker ps -a
5 停止容器
docker stop 容器名字/id號
6 啟動容器
docker start 容器id/名字 # id號只要能夠區分即可無需寫全部
# 設定加速(之前去https://hub.docker.com/),阿里雲,清華,做了一個備份,設定好以後,再拉映象會去國內地址拉取
第一步:vi /etc/docker/daemon.json
第二步:
# 指定清華源,提升拉取加速
{
"registry-mirrors": ["https://docker.mirrors.ustc.edu.cn"]
}
# 作用:
利用映象建立出一個Created 狀態的待啟動容器
# 命令格式:
docker create [OPTIONS] IMAGE [COMMAND] [ARG...]
# 命令引數(OPTIONS):檢視更多
-t, --tty 分配一個偽TTY,也就是分配虛擬終端
-i, --interactive 即使沒有連線,也要保持STDIN開啟
--name 為容器起名,如果沒有指定將會隨機產生一個名稱
# 命令引數(COMMAND\ARG):
COMMAND 表示容器啟動後,需要在容器中執行的命令,如ps、ls 等命令
ARG 表示執行 COMMAND 時需要提供的一些引數,如ps 命令的 aux、ls命令的-a等等
# 建立容器命令演示:
docker create --name test-container centos:centos7 ps -A
# 我們建立了一個容器,並指定在啟動容器的時候執行:docker ps -a
docker create -ti --name test-container2 centos /bin/bash
# 作用:
將一個或多個處於建立狀態或關閉狀態的容器啟動起來
# 命令格式:
docker start [OPTIONS] CONTAINER [CONTAINER...]
# 命令引數(OPTIONS):
-a, --attach 將當前shell的 STDOUT/STDERR 連線到容器上
-i, --interactive 將當前shell的 STDIN連線到容器上
# 命令演示:
docker ps -a
docker start -a 65ebc
docker start test-container
# 容器一直執行的原因COMMAND
1.它有一條前臺程序,一直在執行
2.以後如果自己製作的映象,執行起容器,必須有個可以夯住的命令COMMAND
3.如果COMMAND該命令結束,該容器也就結束了
# 當我們在後臺啟動的時候
1.比如:docker run -di --name=mycentos centos:centos7
2.這時他會自動啟動一個 /bin/bash視窗
3.因為我們並沒有關閉這個/bin/bash視窗,所以他會一直在後臺執行
4.我們在使用start或者直接run進入這個映象的時候,就相當於執行的這個命令:/bin/bash,就進入了這個bash視窗,相當於進入了容器(其實不是進入了容器,可以把他看作是xshell一個遠端連線,連線到這個容器。)這裡我們看作是進入到了這個容器,當我們使用exit退出的時候,就相當於關閉了/bin/bash這個視窗。所以容器一直會在後臺執行的原因就是這個/bin/bash視窗一直在啟動這,沒有關閉它
# 建立並啟動(run)
# 引數:
-i:表示執行容器
-t:表示容器啟動後會進入其命令列。加入這兩個引數後,容器建立就能登入進去。即分配一個偽終端。
-d:在run後面加上-d引數,則會建立一個守護式容器在後臺執行(這樣建立容器後不會自動登入容器,如果只加-i -t兩個引數,建立後就會自動進去容器)。
--name :為建立的容器命名。如果不寫,會自動分配一個名字(英文人名)
-v:表示目錄對映關係(前者是宿主機目錄,後者是容器目錄,對映到宿主機上的目錄),可以使用多個-v做多個目錄或檔案對映。注意:最好做目錄對映,在宿主機上做修改,然後共用到容器上。(下述單獨演示)
-p:表示埠對映,前者是宿主機埠,後者是容器內的對映埠。可以使用多個-p做多個埠對映 (下述單獨演示)
# 例子:run
docker run -it --name=myredis redis # 這時就會啟動redis容器並進去redis容器
docker run -id --name=oursql mysql # 這時就不會進入mysql容器,再後臺執行
# 注意,docker run 映象
使用該命令:如果本地沒有,會先pull,再run
# 方式1:
1.查詢機器上執行的容器
docker ps
2.進入容器
docker exec -it 容器id/bin/bash
docker exec -it 427 /bin/bash
# 第二種:ssh連線(容器內部裝ssh伺服器端)(不常用)
# exec真正的作用是在容器內執行命令,而不是真正的進入到容器內部
1.因為 /bin/bash這個命令,就相當於與這個容器建立了連線,所以我們可以和容器做互動,當我們關閉這個連線的時候,就會自動結束掉這個容器。
2.執行exec命令:
docker exec -it 容器id ls # 查詢根路徑所有檔案
# top 命令(容器內部執行查詢程序)
# 容器內部是純淨的空間,安裝:vim
# 命令:exit
1.如果是一個夯在哪裡得命令,則使用exit退出容器
2.如果不是則會自動退出容器
# -it 進入容器退出(前臺容器自動結束【後臺停止執行】)
1.在我們使用 -it 引數直接進入該容器的時候,使用exit退出的時候這個容器就會自動結束。
- 此時後臺就沒有該執行中的容器。
# -id 進入容器退出(前臺容器自動結束【後臺正常執行】)
2.如果使用 -id 後臺執行容器的時候,使用 docker exec進入該容器,此時使用exit退出該容器的話,只是退出該容器,並沒有從後臺結束該容器,該容器還會在後臺執行這。
# 1.從宿主機拷貝到容器內部
docker cp 宿主機檔案 容器id:容器路徑
docker cp /home/a.txt 427:/home
# 2.從容器中拷貝到宿主機
docker cp 容器id:容器路徑 宿主機路徑(起別名)
docker cp 427:home/a.txt a.txt
# 目錄掛載格式:
docker run -di --name=mycentos99 -v /宿主機要掛載目錄:/容器要掛載路徑 指定映象
docker run -di --name=mycentos99 -v /home:/home centos:centos7
# -v : 對映
# 掛載作用:
1.一旦掛載,以後宿主機目錄內修改,同樣影響容器內部
2.容器內修改同樣影響宿主機
# 命令:
- 使用引數 -p 宿主機埠:容器埠
- 例:docker run -it -p 6377:6379 redis # 將宿主機得6377埠對映到容器redis6379埠上
# 演示:
# 建立容器
- docker run -di -p 6377:6379 redis
# 進入容器
- docker exec -it 27d /bin/bash
- 此時啟動的是redis伺服器端
# 連線使用者端
- redis-cli
# 在容器中操作redis
- set name born
# 此時我們使用遠端連線我們得宿主機雲伺服器的6377埠。
# 為什麼會後臺啟動redis服務?
1.我們在啟動redis容器的時候,他會自動執行一個指令碼檔案:docker-entrypoint.sh
2.就像啟動cent os自動啟動一個/bin/bash視窗
3.而redis啟動/bin/bash與之建立連線之後,會自動執行這個指令碼檔案
# docker-entrypoint.sh 這個指令碼的路徑:
/usr/local/bin/docker-entrypoint.sh
# 命令:
# 檢視容器詳細資訊
- docker inspect 容器id
# 只檢視容器ip地址
- docker inspect --format='{{.NetworkSettings.IPAddress}}' 容器名稱/容器ID
# 其實宿主機與容器之間是通過閘道器進行通訊的
- 檢視閘道器
# 容器內下載該命令:
- 下載檢視ip資訊的命令:yum install net-tools
- ifconfig:檢視網路相關資訊
# 所以此時我們在連線redis的時候就有兩種方式
- 第一種:
- 因為我們做了埠對映,所以我們可以通過:雲伺服器地址:6377連線
- 第二種:
- 此時我們已經知道了容器的ip地址,所以就可以通過: 容器的ip地址:6379 (此時埠號就是它本身的6379因為是直接通過它本身的ip建立的連線)
# 每個容器都有ip地址,每一個ip地址標誌著一臺唯一伺服器,所以就實現了宿主與容器之間的隔離性,每一個容器就相當於一個虛擬機器器
# 在容器內部署mysql
# 容器內查詢env,環境變數密碼
docker run -di --name=mysql -p 3307:3306 -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7
# -e : 表示環境變數指定密碼
# 進入容器
docker exec -it 749 /bin/bash
mysql
mysql -uroot -p 123456
show databases;
drop database lqz;
# 官方提供的
docker run --name some-mysql -v /my/own/datadir:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag
# 宿主部署容器內redis
docker run -di -p 6377:6379 redis:latest
# 宿主部署容器內nginx
docker run -di --name=mynginx -p 8080:80 nginx
# 我們都使用了 -p 引數做了埠對映,所以我們在存取雲伺服器指定對映埠後,就存取到部署好的容器,所以有了docker完全就需要在本地下載這些應用,直接使用docker pull拉下來使用即可