Docker 最初是 dotCloud
公司創始人Solomon Hykes在法國期間發起的一個公司內部項目,它是基於 dotCloud
公司多年雲服務技術的一次革新,並於2013 年 3 月以 Apache 2.0 受權協議開源,主要項目代碼在GitHub上進行維護。Docker
項目後來還加入了 Linux 基金會,併成立推進開放容器聯盟(OCI)。php
Docker 自開源後受到普遍的關注和討論,至今其GitHub 項目 已經超過 5 萬 4 千個星標和一萬多個 fork
。甚至因爲 Docker
項目的火爆,在 2013
年末,dotCloud 公司決定更名爲 Docker]。Docker
最初是在 Ubuntu 12.04
上開發實現的;Red Hat
則從 RHEL 6.5
開始對 Docker
進行支持;Google
也在其 PaaS
產品中普遍應用 Docker
。css
Docker 使用 Google
公司推出的 Go 語言 進行開發實現,基於 Linux
內核的 cgroup,namespace,以及 AUFS 類的 Union FS 等技術,對進程進行封裝隔離,屬於 操做系統層面的虛擬化技術。因爲隔離的進程獨立於宿主和其它的隔離的進程,所以也稱其爲容器。最初實現是基於 LXC,從 0.7 版本之後開始去除 LXC
,轉而使用自行開發的 libcontainer,從 1.11 開始,則進一步演進爲使用 runC 和 containerd。html
runc
是一個 Linux 命令行工具,用於根據 OCI容器運行時規範 建立和運行容器。html5
containerd
是一個守護程序,它管理容器生命週期
,提供了在一個節點上執行容器和管理鏡像的最小功能集。linux
Docker 在容器的基礎上,進行了進一步的封裝,從文件系統、網絡互聯到進程隔離等等,極大的簡化了容器的建立和維護。使得 Docker
技術比虛擬機技術更爲輕便、快捷。nginx
下面的圖片比較了 Docker 和傳統虛擬化方式的不一樣之處。傳統虛擬機技術是虛擬出一套硬件後,在其上運行一個完整操做系統,在該系統上再運行所需應用進程;而容器內的應用進程直接運行於宿主的內核,容器內沒有本身的內核,並且也沒有進行硬件虛擬。所以容器要比傳統虛擬機更爲輕便。git
做爲一種新興的虛擬化方式,Docker
跟傳統的虛擬化方式相比具備衆多的優點。github
因爲容器不須要進行硬件虛擬以及運行完整操做系統等額外開銷,
Docker 對系統資源的利用率更高。不管是應用執行速度、內存損耗或者文件存儲速度,都要比傳統虛擬機技術更高效。所以,相比虛擬機技術,一個相同配置的主機,每每能夠運行更多數量的應用。
golang
傳統的虛擬機技術啓動應用服務每每須要數分鐘,而
Docker 容器應用,因爲直接運行於宿主內核,無需啓動完整的操做系統,所以能夠作到秒級、甚至毫秒級的啓動時間。大大的節約了開發、測試、部署的時間。
web
開發過程當中一個常見的問題是環境一致性問題。因爲開發環境、測試環境、生產環境不一致,致使有些 bug 並未在開發過程當中被發現。而
Docker 的鏡像提供了除內核外完整的運行時環境,確保了應用運行環境一致性,從而不會再出現 *「這段代碼在我機器上沒問題啊」* 這類問題。
對開發和運維(DevOps)人員來講,最但願的就是一次建立或配置,能夠在任意地方正常運行。
使用 Docker
能夠經過定製應用鏡像來實現持續集成、持續交付、部署。開發人員能夠經過 Dockerfile 來進行鏡像構建,並結合 持續集成(Continuous Integration) 系統進行集成測試,而運維人員則能夠直接在生產環境中快速部署該鏡像,甚至結合 持續部署(Continuous Delivery/Deployment) 系統進行自動部署。
並且使用 Dockerfile
使鏡像構建透明化,不只僅開發團隊能夠理解應用運行環境,也方便運維團隊理解應用運行所需條件,幫助更好的生產環境中部署該鏡像。
因爲 Docker
確保了執行環境的一致性,使得應用的遷移更加容易。Docker
能夠在不少平臺上運行,不管是物理機、虛擬機、公有云、私有云,甚至是筆記本,其運行結果是一致的。所以用戶能夠很輕易的將在一個平臺上運行的應用,遷移到另外一個平臺上,而不用擔憂運行環境的變化致使應用沒法正常運行的狀況。
Docker
使用的分層存儲以及鏡像的技術,使得應用重複部分的複用更爲容易,也使得應用的維護更新更加簡單,基於基礎鏡像進一步擴展鏡像也變得很是簡單。此外,Docker
團隊同各個開源項目團隊一塊兒維護了一大批高質量的 官方鏡像,既能夠直接在生產環境使用,又能夠做爲基礎進一步定製,大大的下降了應用服務的鏡像製做成本。
特性 | 容器 | 虛擬機 |
---|---|---|
啓動 | 秒級 | 分鐘級 |
硬盤使用 | 通常爲 MB |
通常爲 GB |
性能 | 接近原生 | 弱於 |
系統支持量 | 單機支持上千個容器 | 通常幾十個 |
Docker前世: 1.chroot實現切根,隔離操做系統。 2.namespaces實現進程、掛載、網絡等的隔離 UTS、MOUNT、TCP、PID、USER、NETWORK 3.ccgroup實現資源調度、銷燬等 Docker此生: LXC---->Dcoker LinuXContainer:封裝上述經常使用功能用於調用,便於容器的建立、使用、銷燬。 Docker:EE企業版、CE社區版 Docker 是 Docker.Inc 公司開源的一個基於 LXC技術之上構建的Container容器引擎, 源代碼託管在 GitHub 上, 基於Go語言並聽從Apache2.0協議開源。 Docker是經過內核虛擬化技術(namespaces及cgroups等)來提供容器的資源隔離與安全保障等。因爲Docker經過操做系統層的虛擬化實現隔離,因此Docker容器在運行時,不須要相似虛擬機(VM)額外的操做系統開銷,提升資源利用率。 Docker 包括三個基本概念 鏡像(Image) 容器(Container) 倉庫(Repository) Image(鏡像): 那麼鏡像究竟是什麼呢?Docker 鏡像能夠看做是一個特殊的文件系統,除了提供容器運行時所需的程序、庫、資源、配置等文件外,還包含了一些爲運行時準備的一些配置參數(如匿名卷、環境變量、用戶等)。 Container(容器) 容器(Container)的定義和鏡像(Image)幾乎如出一轍,也是一堆層統一視角,惟一區別在於容器最上面那一層是可讀可寫的。 Repository(倉庫) 鏡像倉庫是 Docker 用來集中存放鏡像文件的地方,相似於咱們以前經常使用的代碼倉庫。 一般,一個倉庫會包含同一個軟件不一樣版本的鏡像,而標籤就經常使用於對應該軟件的各個版本 。 咱們能夠經過<倉庫名>:<標籤>的格式來指定具體是這個軟件哪一個版本的鏡像。若是不給出標籤,將以 Latest 做爲默認標籤。
docker鏡像 Docker 鏡像(Image),就至關因而一個 root 文件系統。好比官方鏡像 ubuntu:18.04 就包含了完整的一套 Ubuntu 18.04 最小系統的 root 文件系統。 Docker 鏡像是一個特殊的文件系統,除了提供容器運行時所需的程序、庫、資源、配置等文件外,還包含了一些爲運行時準備的一些配置參數(如匿名卷、環境變量、用戶等)。鏡像不包含任何動態數據,其內容在構建以後也不會被改變。 分層存儲 由於鏡像包含操做系統完整的 root 文件系統,其體積每每是龐大的,所以在 Docker 設計時,就充分利用 Union FS 的技術,將其設計爲分層存儲的架構。因此嚴格來講,鏡像並不是是像一個 ISO 那樣的打包文件,鏡像只是一個虛擬的概念,其實際體現並不是由一個文件組成,而是由一組文件系統組成,或者說,由多層文件系統聯合組成。 鏡像構建時,會一層層構建,前一層是後一層的基礎。每一層構建完就不會再發生改變,後一層上的任何改變只發生在本身這一層。好比,刪除前一層文件的操做,實際不是真的刪除前一層的文件,而是僅在當前層標記爲該文件已刪除。在最終容器運行的時候,雖然不會看到這個文件,可是實際上該文件會一直跟隨鏡像。所以,在構建鏡像的時候,須要額外當心,每一層儘可能只包含該層須要添加的東西,任何額外的東西應該在該層構建結束前清理掉。 分層存儲的特徵還使得鏡像的複用、定製變的更爲容易。甚至能夠用以前構建好的鏡像做爲基礎層,而後進一步添加新的層,以定製本身所需的內容,構建新的鏡像。
Docker 容器 鏡像(Image)和容器(Container)的關係,就像是面向對象程序設計中的 類 和 實例 同樣,鏡像是靜態的定義,容器是鏡像運行時的實體。容器能夠被建立、啓動、中止、刪除、暫停等。 容器的實質是進程,但與直接在宿主執行的進程不一樣,容器進程運行於屬於本身的獨立的 命名空間。所以容器能夠擁有本身的 root 文件系統、本身的網絡配置、本身的進程空間,甚至本身的用戶 ID 空間。容器內的進程是運行在一個隔離的環境裏,使用起來,就好像是在一個獨立於宿主的系統下操做同樣。這種特性使得容器封裝的應用比直接在宿主運行更加安全。也由於這種隔離的特性,不少人初學 Docker 時經常會混淆容器和虛擬機。 前面講過鏡像使用的是分層存儲,容器也是如此。每個容器運行時,是以鏡像爲基礎層,在其上建立一個當前容器的存儲層,咱們能夠稱這個爲容器運行時讀寫而準備的存儲層爲 容器存儲層。 容器存儲層的生存週期和容器同樣,容器消亡時,容器存儲層也隨之消亡。所以,任何保存於容器存儲層的信息都會隨容器刪除而丟失。 按照 Docker 最佳實踐的要求,容器不該該向其存儲層內寫入任何數據,容器存儲層要保持無狀態化。全部的文件寫入操做,都應該使用 數據卷(Volume)、或者綁定宿主目錄,在這些位置的讀寫會跳過容器存儲層,直接對宿主(或網絡存儲)發生讀寫,其性能和穩定性更高。 數據卷的生存週期獨立於容器,容器消亡,數據卷不會消亡。所以,使用數據卷後,容器刪除或者從新運行以後,數據卻不會丟失。
Docker Registry 鏡像構建完成後,能夠很容易的在當前宿主機上運行,可是,若是須要在其它服務器上使用這個鏡像,咱們就須要一個集中的存儲、分發鏡像的服務,Docker Registry 就是這樣的服務。 一個 Docker Registry 中能夠包含多個 倉庫(Repository);每一個倉庫能夠包含多個 標籤(Tag);每一個標籤對應一個鏡像。 一般,一個倉庫會包含同一個軟件不一樣版本的鏡像,而標籤就經常使用於對應該軟件的各個版本。咱們能夠經過 <倉庫名>:<標籤> 的格式來指定具體是這個軟件哪一個版本的鏡像。若是不給出標籤,將以 latest 做爲默認標籤。 以 Ubuntu 鏡像 爲例,ubuntu 是倉庫的名字,其內包含有不一樣的版本標籤,如,16.04, 18.04。咱們能夠經過 ubuntu:16.04,或者 ubuntu:18.04 來具體指定所需哪一個版本的鏡像。若是忽略了標籤,好比 ubuntu,那將視爲 ubuntu:latest。 倉庫名常常以 兩段式路徑 形式出現,好比 jwilder/nginx-proxy,前者每每意味着 Docker Registry 多用戶環境下的用戶名,後者則每每是對應的軟件名。但這並不是絕對,取決於所使用的具體 Docker Registry 的軟件或服務。 Docker Registry 公開服務 Docker Registry 公開服務是開放給用戶使用、容許用戶管理鏡像的 Registry 服務。通常這類公開服務容許用戶免費上傳、下載公開的鏡像,並可能提供收費服務供用戶管理私有鏡像。 最常使用的 Registry 公開服務是官方的 Docker Hub,這也是默認的 Registry,並擁有大量的高質量的官方鏡像。除此之外,還有 CoreOS 的 Quay.io,CoreOS 相關的鏡像存儲在這裏;Google 的 Google Container Registry,Kubernetes 的鏡像使用的就是這個服務。 因爲某些緣由,在國內訪問這些服務可能會比較慢。國內的一些雲服務商提供了針對 Docker Hub 的鏡像服務(Registry Mirror),這些鏡像服務被稱爲加速器。常見的有 阿里雲加速器、DaoCloud 加速器 等。使用加速器會直接從國內的地址下載 Docker Hub 的鏡像,比直接從 Docker Hub 下載速度會提升不少。在 安裝 Docker 一節中有詳細的配置方法。 國內也有一些雲服務商提供相似於 Docker Hub 的公開服務。好比 時速雲鏡像倉庫、網易雲鏡像服務、DaoCloud 鏡像市場、阿里雲鏡像庫 等。 私有 Docker Registry 除了使用公開服務外,用戶還能夠在本地搭建私有 Docker Registry。Docker 官方提供了 Docker Registry 鏡像,能夠直接使用作爲私有 Registry 服務。在 私有倉庫 一節中,會有進一步的搭建私有 Registry 服務的講解。 開源的 Docker Registry 鏡像只提供了 Docker Registry API 的服務端實現,足以支持 docker 命令,不影響使用。但不包含圖形界面,以及鏡像維護、用戶管理、訪問控制等高級功能。在官方的商業化版本 Docker Trusted Registry 中,提供了這些高級功能。 除了官方的 Docker Registry 外,還有第三方軟件實現了 Docker Registry API,甚至提供了用戶界面以及一些高級功能。好比,Harbor 和 Sonatype Nexus。
國內源安裝部署: 1.更改源爲清華源 wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo yum remove docker docker-common docker-selinux docker-engine yum install -y yum-utils device-mapper-persistent-data lvm2 wget -O /etc/yum.repos.d/docker-ce.repo https://download.docker.com/linux/centos/docker-ce.repo sed -i 's+download.docker.com+mirrors.tuna.tsinghua.edu.cn/docker-ce+' /etc/yum.repos.d/docker-ce.repo yum makecache fast yum install -y docker-ce 2.建立國內源鏡像加速配置 mkdir -p /etc/docker tee /etc/docker/daemon.json<<EOF { "registry-mirrors": ["http://hub-mirror.c.163.com"] } EOF 3.從新加載並啓動docker systemctl daemon-reload systemctl start docker 4.問題: docker的安裝目錄:rpm -ql docker-ce docker的日誌在哪裏? 拉取的鏡像放在哪裏?
[root@docker01 ~]# docker login docker.io Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one. Username: Your UserName Password: Your PassWord WARNING! Your password will be stored unencrypted in /root/.docker/config.json. Configure a credential helper to remove this warning. See https://docs.docker.com/engine/reference/commandline/login/#credentials-store Login Succeeded [root@docker01 ~]# cat /root/.docker/config.json { "auths": { "https://index.docker.io/v1/": { "auth": "bGVvbjk1Mjc6eGlhQDE3NzI3NDg5NTI3" } }, "HttpHeaders": { "User-Agent": "Docker-Client/19.03.5 (linux)" }
docker search alpine
docker pull alpine
docker images docker image ls
docker tag fce289e99eb9 docker.io/leon9527/hello-world:v3.10.1
docker push docker.io/leon9527/hello-world:v3.10.1
docker rmi docker.io/leon9527/hello-world:v3.10.1 #刪除tag docker rmi imageID #刪鏡像 -f 強制刪除
導出鏡像 docker image save 470671670cac >/tmp/centos.tar.gz docker save -o centos.tar centos:latest docker save centos:latest -o centos.tar.gz docker save <repository>:<tag> -o <repository>.tar #若是導出時不加標籤,(會致使載入鏡像後名字標籤都爲<none>) 導入鏡像 docker load </tmp/centos.tar.gz docker load -i /tmp/centos.tar.gz
總結: 搜索鏡像,選擇鏡像建議: 1.優先選擇官方的 2.選擇星星多的 docker search centos 查看鏡像 [root@m01 ~]# docker images 或者 docker image ls 或者 docker images --no-trunc #顯示詳細信息 REPOSITORY TAG IMAGE ID CREATED SIZE centos latest 470671670cac 2 weeks ago 237MB 識別鏡像惟一性的方法: 1.REPOSITORY:TAG 2.IMAGE ID(sha256:64位號碼,默認只截取12位) 獲取鏡像 docker pull centos docker pull busybox docker pull busybox:1.29 鏡像詳細信息查看 docker image inspect busybox:1.29 只查看鏡像id docker images -q 刪除鏡像 docker rmi centos:latest docker image rm 470671670cac docker image rm -f `docker images -q` #刪除所有鏡像 docker image rm -f $(docker images -q) 導出鏡像 docker image save 470671670cac >/tmp/centos.tar.gz docker save -o centos.tar centos:latest docker save centos:latest -o centos.tar.gz docker save <repository>:<tag> -o <repository>.tar #若是導出時不加標籤,(會致使載入鏡像後名字標籤都爲<none>) 導入鏡像 docker load </tmp/centos.tar.gz docker load -i /tmp/centos.tar.gz 修改鏡像名稱和標籤 docker image tag 470671670cac centos:latest #不能大寫,必須小寫 若是鏡像和標籤已存在,從新打標籤就至關於給鏡像添加了一個硬連接,由於兩個標籤的鏡像id是同樣的 docker tag 5ad3bd0e67a9 oldxia/nginx:v1.0 [root@m01 ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE nginx latest 5ad3bd0e67a9 11 days ago 127MB oldxia/nginx v1.0 5ad3bd0e67a9 11 days ago 127MB
啓動容器 docker run --name mydocker -t -i centos /bin/bash docker run -it --name mydocker --rm 470671670cac #退出後自動刪除容器 啓動中止的容器 docker start 容器ID #不進入容器 docker start -i 容器ID #進入容器 查看容器 docker ps #查看正在運行的容器 ☆☆☆☆☆ docker ps -a #查看全部狀態的容器 ☆☆☆☆☆ docker ps -q #查看正在運行的容器ID ☆☆☆☆☆ docker ps -aq #僅查看全部容器的ID ☆☆☆☆☆ [root@m01 ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES c1a86a498c79 470671670cac "/bin/bash" 54 seconds ago Up 53 seconds centos 中止容器 docker stop 容器ID 容器類別: 交互式容器(centos)---->開發測試 守護式容器(nginx) ---->運行服務 docker run --name nginx -p 8080:80 -d nginx ☆☆☆☆☆ 進入容器: docker exec會分配一個新的終端tty(子進程方式) ☆☆☆☆☆ docker exec -it 容器ID /bin/bash docker attach會使用同一個終端(複用原來的終端,相似兩個終端是鏡像,操做都是同樣的) docker attach 容器ID 刪除單個容器 docker rm 容器ID 批量刪除容器 docker stop $(docker ps -q) docker rm $(docker ps -aq) 生產:for i in `docker ps -a|grep -i exit|awk '{print $1}'`;do docker rm -f $i;done 查看容器的進程 docker top ContainerID == docker container top containerID 查看容器的日誌 docker container logs containerID docker container logs -f containerID #實時監控 -tf:顯示時間實時監控 -t docker container logs -tf --tail 10 containerName 將容器提交爲新的鏡像 docker commit -p 4b388c4fd729 game:v1.0
指定映射端口: -p 80:80 -p 443:443 #多端口映射 -p 宿主機IP:宿主機端口:容器端口 隨機映射端口 docker run -P -p hostPort:containerPort ★★★★★ -p ip:hostPort:containerPort ★★★★★ -p ip::containerPort #隨機端口 32768-60999 -p ip:hostPort:containerPort/udp #指定容器內部協議 若是想多個容器使用8080端口,能夠經過添加多個IP地址實現: ifconfig eth0:1 10.0.1.13 up docker run -d -p 10.0.1.11:8080:80 nginx:latest docker run -d -p 10.0.1.13:8080:80 nginx:latest 進入容器裏修改站點目錄,而後訪問測試 docker exec -it bdb2a4e7e24d /bin/bash echo "web01" > /usr/share/nginx/html/index.html docker exec -it 31c1de138dda /bin/bash echo "web02" > /usr/share/nginx/html/index.html 訪問測試: [root@m01 ~]# curl 10.0.1.11:8080 web02 [root@m01 ~]# curl 10.0.1.13:8080 web01
[root@docker01 ~]# docker run --rm -e E_OPTS=abcdEFG nginx:1.16.1 printenv PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin HOSTNAME=834fd0ad3bd1 E_OPTS=abcdEFG NGINX_VERSION=1.16.1 NJS_VERSION=0.3.8 PKG_RELEASE=1~buster HOME=/root -e:定義環境變量鍵值對,使用=,能夠傳遞多個環境變量.
docker run -d -p 80:80 nginx:1.16.1 docker exec -it 3a6 /bin/bash 更改源:這個鏡像是debian系列. tee /etc/apt/sources.list << EOF deb http://mirrors.163.com/debian/ jessie main non-free contrib deb http://mirrors.163.com/debian/ jessie-updates main non-free contrib EOF apt-get update && apt-get install curl -y docker commit -p 0b9d0d012fdf leon9527/nginx:curl docker push leon9527/nginx:curl
-v 宿主機目錄:容器內目錄
下面咱們來建立一個html5小遊戲
建立遊戲代碼目錄: mkdir /data/xiaoniao -p cd /data/ unzip xiaoniaofeifei.zip -d xiaoniao /
建立容器並映射數據卷: docker run -d -p 8080:80 -v /data/xiaoniao:/usr/share/nginx/html nginx:latest docker ps 訪問遊戲頁面: 10.0.1.61
--volumes-from (跟某一個已經存在的容器掛載相同的卷)後面跟容器名,不是volume的名字
查看當前容器有哪些卷
docker volume ls
1.下面咱們利用容器卷建立一個小遊戲
建立一個容器卷: docker run -d -p 8080:80 --volume xiaoniao:/usr/share/nginx/html nginx:latest docker volume ls
查看卷的目錄: docker volume inspect xiaoniao
複製代碼目錄到容器卷目錄: \cp -a /data/xiaoniao/* /var/lib/docker/volumes/xiaoniao/_data/
使用容器卷建立新容器 docker run -d -p 8090:80 --volume xiaoniao:/usr/share/nginx/html nginx:latest 或者 docker run -d -p 8091:80 --volumes-from sad_bose nginx:latest #sad_bose爲容器名,以下: 測試訪問: 10.0.1.61:8090
需求:
訪問8080端口,展現xiaoniao首頁
訪問8090端口,展現遊戲集合頁面
準備nginx配置文件: [root@m01 ~]# cat /data/game.conf server { listen 8080; server_name localhost; location / { root /opt/game/; index index.html index.htm; } } server { listen 8090; server_name localhost; location / { root /opt/xiaoniao/; index index.html index.htm; } }
上傳代碼目錄: [root@m01 /data]# ll 總用量 18896 drwxr-xr-x 5 root root 73 9月 7 23:03 game -rw-r--r-- 1 root root 309 9月 7 22:57 game.conf -rw-r--r-- 1 root root 19248295 8月 28 09:48 html5.zip drwxr-xr-x 3 root root 92 9月 7 22:15 xiaoniao -rw-r--r-- 1 root root 91014 9月 7 22:11 xiaoniaofeifei.zip
建立容器並掛載: 須要掛載的內容: 1.nginx配置文件 2.遊戲目錄 建立容器命令 docker run -d -p 8080:8080 -p 8090:8090 -v /data/game.conf:/etc/nginx/conf.d/game.conf -v /data/game:/opt/game -v /data/xiaoniao:/opt/xiaoniao nginx:latest ### 訪問測試 10.0.1.11:8080 10.0.1.11:8090
USER/WORKDIR ADD/COPY RUN/ENV CMD/ENTRYPOINT USER:指定容器運行主進程的用戶 WORKDIR:至關於cd命令,目錄切換
Docker經過對於在Dockerfile中的一系列指令的順序解析實現自動的image的構建 經過使用build命令,根據Dockerfiel的描述來構建鏡像 經過源代碼路徑的方式 經過標準輸入流的方式 Dockerfile指令: 只支持Docker本身定義的一套指令,不支持自定義 大小寫不敏感,可是建議所有使用大寫 根據Dockerfile的內容順序執行 FROM: FROM {base鏡像} 必須放在DOckerfile的第一行,表示從哪一個baseimage開始構建 centos:7 centos@imageID #安全 MAINTAINER: 可選的,用來標識image做者的地方 RUN: 每個RUN指令都會是在一個新的container裏面運行,並提交爲一個image做爲下一個RUN的base 一個Dockerfile中能夠包含多個RUN,按定義順序執行 RUN支持兩種運行方式: RUN <cmd> 這個會看成/bin/sh -c 「cmd」 運行 RUN [「executable」,「arg1」,。。],Docker把他看成json的順序來解析,所以必須使用雙引號,並且executable須要是完整路徑 RUN 都是啓動一個容器、執行命令、而後提交存儲層文件變動。第一層 RUN command1 的執行僅僅是當前進程,一個內存上的變化而已,其結果不會形成任何文件。而到第二層的時候,啓動的是一個全新的容器,跟第一層的容器更徹底不要緊,天然不可能繼承前一層構建過程當中的內存變化。而若是須要將兩條命令或者多條命令聯合起來執行須要加上&&。如:cd /usr/local/src && wget xxxxxxx CMD: CMD的做用是做爲執行container時候的默認行爲(容器默認的啓動命令) 當運行container的時候聲明瞭command,則再也不用image中的CMD默認所定義的命令 一個Dockerfile中只能有一個有效的CMD,當定義多個CMD的時候,只有最後一個纔會起做用 CMD定義的三種方式: CMD <cmd> 這個會看成/bin/sh -c "cmd"來執行 CMD ["executable","arg1",....] CMD ["arg1","arg2"],這個時候CMD做爲ENTRYPOINT的參數 EXPOSE 聲明端口 #雞肋 格式爲 EXPOSE <端口1> [<端口2>...]。 EXPOSE 指令是聲明運行時容器提供服務端口,這只是一個聲明,在運行時並不會由於這個聲明應用就會開啓這個端口的服務。在 Dockerfile 中寫入這樣的聲明有兩個好處,一個是幫助鏡像使用者理解這個鏡像服務的守護端口,以方便配置映射;另外一個用處則是在運行時使用隨機端口映射時,也就是 docker run -P 時,會自動隨機映射 EXPOSE 的端口。 entrypoint: entrypoint的做用是,把整個container變成了一個可執行的文件,這樣不可以經過替換CMD的方法來改變建立container的方式。可是能夠經過參數傳遞的方法影響到container內部 每一個Dockerfile只可以包含一個entrypoint,多個entrypoint只有最後一個有效 當定義了entrypoint之後,CMD只可以做爲參數進行傳遞 entrypoint定義方式: entrypoint ["executable","arg1","arg2"],這種定義方式下,CMD能夠經過json的方式來定義entrypoint的參數,能夠經過在運行container的時候經過指定command的方式傳遞參數 entrypoint <cmd>,看成/bin/bash -c "cmd"運行命令 ADD & COPY: 當在源代碼構建的方式下,能夠經過ADD和COPY的方式,把host上的文件或者目錄複製到image中 ADD和COPY的源必須在context路徑下 當src爲網絡URL的狀況下,ADD指令能夠把它下載到dest的指定位置,這個在任何build的方式下均可以work ADD相對COPY還有一個多的功能,可以進行自動解壓壓縮包,僅支持gzip, bzip2,xz 。 ENV: ENV key value 用來設置環境變量,後續的RUN可使用它所建立的環境變量 當建立基於該鏡像的container的時候,會自動擁有設置的環境變量 WORKDIR: 用來指定當前工做目錄(或者稱爲當前目錄) 當使用相對目錄的狀況下,採用上一個WORKDIR指定的目錄做爲基準 USER: 指定UID或者username,來決定運行RUN指令的用戶 ONBUILD: ONBUILD做爲一個trigger的標記,能夠用來trigger任何Dockerfile中的指令 能夠定義多個ONBUILD指令 當下一個鏡像B使用鏡像A做爲base的時候,在FROM A指令前,會先按照順序執行在構建A時候定義的ONBUILD指令 ONBUILD <DOCKERFILE 指令> <content> VOLUME: 用來建立一個在image以外的mount point,用來在多個container之間實現數據共享 運行使用json array的方式定義多個volume VOLUME ["/var/data1","/var/data2"] 或者plain text的狀況下定義多個VOLUME指令
NAT(默認) None:不對外提供網絡訪問 Host:docker使用宿主機網絡 docker run -d --net=host -p8080:80 nginx:1.16.1 聯合網絡:多個容器共享一個網絡名稱空間 docker run -d --net=container:0b9d0d012fdf nginx:1.16.1 /bin/bash
下面咱們基於centos:7容器製做一個新鏡像,並安裝nginx服務
啓動一個容器並安裝nginx: [root@m01 /backup]# docker pull centos:7 #拉取centos7鏡像 [root@m01 ~]# docker run -it centos /bin/bash [root@4b388c4fd729 ~]# yum install wget install openssh-clients -y [root@4b388c4fd729 ~]# wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo [root@4b388c4fd729 ~]# wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo [root@4b388c4fd729 ~]# sed -i -e '/mirrors.cloud.aliyuncs.com/d' -e '/mirrors.aliyuncs.com/d' /etc/yum.repos.d/CentOS-Base.repo [root@4b388c4fd729 ~]# cat /etc/yum.repos.d/nginx.repo [nginx-stable] name=nginx stable repo baseurl=http://nginx.org/packages/centos/$releasever/$basearch/ gpgcheck=1 enabled=1 gpgkey=https://nginx.org/keys/nginx_signing.key [nginx-mainline] name=nginx mainline repo baseurl=http://nginx.org/packages/mainline/centos/$releasever/$basearch/ gpgcheck=1 enabled=0 gpgkey=https://nginx.org/keys/nginx_signing.key [root@4b388c4fd729 ~]# yum makecache fast [root@4b388c4fd729 ~]# yum install nginx -
上傳代碼目錄並配置nginx配置文件 #先要在容器裏面使用ssh鏈接到宿主機eth0作認證 [root@4b388c4fd729 opt]# scp -P 9527 -r 10.0.1.61:/html/* /opt/ [root@4b388c4fd729 /]# ll /opt/ total 18896 drwxr-xr-x 5 root root 73 Sep 7 16:02 game -rw-r--r-- 1 root root 303 Sep 7 16:02 game.conf -rw-r--r-- 1 root root 19248295 Sep 7 16:02 html5.zip drwxr-xr-x 3 root root 92 Sep 7 16:02 xiaoniao -rw-r--r-- 1 root root 91014 Sep 7 16:02 xiaoniaofeifei.zip [root@4b388c4fd729 /]# cp /opt/game.conf /etc/nginx/conf.d/ [root@4b388c4fd729 ~]# cat /etc/nginx/conf.d/game.conf server { listen 8080; server_name localhost; location / { root /opt/game; index index.html index.htm; } } server { listen 8090; server_name localhost; location / { root /opt/birds; index index.html index.htm; } }
將容器提交爲新的鏡像: #鏡像在本地:/var/lib/docker/image/overlay2/imagedb/content/sha256/目錄下 [root@m01 /html]# docker commit 4b388c4fd729 game:v1.0 sha256:11ce7847c118ca2af232cf93d13382b6c4bec67329f1455151ac83b9304f8ed9 [root@m01 /backup]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE game v1.0 11ce7847c118 6 minutes ago 422MB nginx latest 2073e0bcb60e 23 hours ago 127MB centos 7 5e35e350aded 2 months ago 203MB
測試鏡像功能是否可用: [root@m01 /html]# docker run -d -p 8080:8080 -p 8090:8090 game:v1.0 nginx -g 'daemon off;' 4afdd6d9a5d45d3b9bc07ed6c17fd92863ce3288df55d3f677b35448a0deb66e [root@m01 ~]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 4afdd6d9a5d4 game:v1.0 "nginx -g 'daemon of…" 17 minutes ago Up 17 minutes 0.0.0.0:8080->8080/tcp, 0.0.0.0:8090->8090/tcp inspiring_kepler 4b388c4fd729 5e35e350aded "/bin/bash" 2 hours ago Up 2 hours centos7
將新鏡像導出 docker save -o game_v1.tar game:v1.0
建立容器: #使用上面的遊戲鏡像 docker run -d -p 80:80 --name cloud game:v1.0 nginx -g 'daemon off;'
進入容器安裝php並修改運行用戶: docker exec -it cloud /bin/bash yum install php-fpm -y [root@f4ed585de854 /]# php-fpm -v PHP 5.4.16 (fpm-fcgi) (built: Nov 1 2019 16:05:34) Copyright (c) 1997-2013 The PHP Group Zend Engine v2.4.0, Copyright (c) 1998-2013 Zend Technologies sed -i '/^user/c user = nginx' /etc/php-fpm.d/www.conf sed -i '/^group/c group = nginx' /etc/php-fpm.d/www.conf sed -i '/daemonize/s#no#yes#g' /etc/php-fpm.conf php-fpm -c /etc/php.ini -y /etc/php-fpm.conf ps -ef|grep php
在容器中配置nginx: [root@d0c987bcefa2 /]# cat /etc/nginx/conf.d/cloud.conf server { listen 80; server_name 10.0.0.61; root /code; index index.php index.html; location ~ \.php$ { root /code; fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } } nginx -t nginx -s reload
在容器中下載代碼目錄: mkdir /code cd /code scp -P 9527 -r 10.0.61:/backup/kod/* . [root@f4ed585de854 code]# ls ChangeLog.md README.MD app config data index.php plugins static [root@f4ed585de854 code]# chown -R nginx.nginx /code
測試: [root@f4ed585de854 code]# curl -I 127.0.0.1 HTTP/1.1 302 Moved Temporarily Server: nginx/1.16.1 Date: Mon, 03 Feb 2020 07:53:02 GMT Content-Type: text/html; charset=utf-8 Connection: keep-alive X-Powered-By: PHP/5.4.16 Set-Cookie: KOD_SESSION_ID_9d6d9=cbk6rfc8p3s2gl4n26fpen10b3; path=/ Set-Cookie: KOD_SESSION_ID_9d6d9=cbk6rfc8p3s2gl4n26fpen10b3; path=/ Set-Cookie: KOD_SESSION_ID_9d6d9=cbk6rfc8p3s2gl4n26fpen10b3; path=/ Set-Cookie: KOD_SESSION_SSO=k06nfral3ls0v26l67i7u0jvu3; path=/ Expires: Thu, 19 Nov 1981 08:52:00 GMT Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0 Pragma: no-cache Set-Cookie: KOD_SESSION_ID_9d6d9=deleted; expires=Thu, 01-Jan-1970 00:00:01 GMT; path=/ Set-Cookie: kod_name=deleted; expires=Thu, 01-Jan-1970 00:00:01 GMT Set-Cookie: kodToken=deleted; expires=Thu, 01-Jan-1970 00:00:01 GMT Set-Cookie: X-CSRF-TOKEN=deleted; expires=Thu, 01-Jan-1970 00:00:01 GMT Location: ./index.php?user/login
測試提交新的鏡像: [root@m01 /backup]# docker commit f4ed585de854 cloud:v1.0 sha256:2ac6a6783da9bf4cbccbb521ff91e80ee95a60786ae012b3aff5701ea9d2dd31 [root@m01 /backup]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE cloud v1.0 2ac6a6783da9 10 seconds ago 633MB game v1.0 11ce7847c118 About an hour ago 422MB nginx latest 2073e0bcb60e 24 hours ago 127MB centos 7 5e35e350aded 2 months ago 203MB 編寫啓動腳本並提交新鏡像: [root@f4ed585de854 /]# cat init.sh #!/bin/bash php-fpm -c /etc/php.ini -y /etc/php-fpm.conf nginx -g 'daemon off;' [root@f4ed585de854 /]# chmod +x init.sh [root@f4ed585de854 /]# ll init.sh -rwxr-xr-x 1 root root 80 Feb 3 07:57 init.sh [root@m01 /backup]# docker commit f4ed585de854 cloud:v2.0 sha256:49889648236b6bb3d928ed51d281360771ff71b0f96f53f3f537b107c0641c26
使用cloud:v2.0鏡像啓動新容器測試: docker stop $(docker ps -qa) [root@m01 /backup]# docker run -d --name yunpan -p 80:80 cloud:v2.0 /bin/bash /init.sh 343f3ac70dddef8005b00c5170b526cea313d5cf86c3aeb078e7eaf0217cfe95 [root@m01 /backup]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 343f3ac70ddd cloud:v2.0 "/bin/bash /init.sh" About a minute ago Up 0.0.0.0:80->80/tcp yunpan
添加GD庫: 此時打開頁面提示缺乏GD庫,進入容器內安裝php支持插件,而後重啓容器 [root@m01 /backup]# docker exec -it yunpan /bin/bash [root@343f3ac70ddd /]# yum install php-mbstring php-gd -y [root@m01 /backup]# docker restart yunpan yunpan 訪問測試沒問題後提交新鏡像: [root@m01 /backup]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 343f3ac70ddd cloud:v2.0 "/bin/bash /init.sh" About a minute ago Up 0.0.0.0:80->80/tcp yunpan [root@m01 /backup]# docker commit 343f3ac70ddd cloud:v2.0 sha256:19081f99dd73d86546647419ef42456cd4bdb8618444592298f8ef803c59e727 [root@m01 /backup]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE cloud v2.0 19081f99dd73 9 seconds ago 812MB cloud v1.0 2ac6a6783da9 18 minutes ago 633MB game v1.0 11ce7847c118 2 hours ago 422MB nginx latest 2073e0bcb60e 24 hours ago 127MB centos 7 5e35e350aded 2 months ago 203MB
Docker經過對於在Dockerfile中的一系列指令的順序解析實現自動的image的構建 經過使用build命令,根據Dockerfiel的描述來構建鏡像 經過源代碼路徑的方式 經過標準輸入流的方式 Dockerfile指令: 只支持Docker本身定義的一套指令,不支持自定義 大小寫不敏感,可是建議所有使用大寫 根據Dockerfile的內容順序執行 FROM: FROM {base鏡像} 必須放在DOckerfile的第一行,表示從哪一個baseimage開始構建 centos:7 centos@imageID #安全 MAINTAINER: 可選的,用來標識image做者的地方 RUN: 每個RUN指令都會是在一個新的container裏面運行,並提交爲一個image做爲下一個RUN的base 一個Dockerfile中能夠包含多個RUN,按定義順序執行 RUN支持兩種運行方式: RUN <cmd> 這個會看成/bin/sh -c 「cmd」 運行 RUN [「executable」,「arg1」,。。],Docker把他看成json的順序來解析,所以必須使用雙引號,並且executable須要是完整路徑 RUN 都是啓動一個容器、執行命令、而後提交存儲層文件變動。第一層 RUN command1 的執行僅僅是當前進程,一個內存上的變化而已,其結果不會形成任何文件。而到第二層的時候,啓動的是一個全新的容器,跟第一層的容器更徹底不要緊,天然不可能繼承前一層構建過程當中的內存變化。而若是須要將兩條命令或者多條命令聯合起來執行須要加上&&。如:cd /usr/local/src && wget xxxxxxx CMD: CMD的做用是做爲執行container時候的默認行爲(容器默認的啓動命令) 當運行container的時候聲明瞭command,則再也不用image中的CMD默認所定義的命令 一個Dockerfile中只能有一個有效的CMD,當定義多個CMD的時候,只有最後一個纔會起做用 CMD定義的三種方式: CMD <cmd> 這個會看成/bin/sh -c "cmd"來執行 CMD ["executable","arg1",....] CMD ["arg1","arg2"],這個時候CMD做爲ENTRYPOINT的參數 EXPOSE 聲明端口 格式爲 EXPOSE <端口1> [<端口2>...]。 EXPOSE 指令是聲明運行時容器提供服務端口,這只是一個聲明,在運行時並不會由於這個聲明應用就會開啓這個端口的服務。在 Dockerfile 中寫入這樣的聲明有兩個好處,一個是幫助鏡像使用者理解這個鏡像服務的守護端口,以方便配置映射;另外一個用處則是在運行時使用隨機端口映射時,也就是 docker run -P 時,會自動隨機映射 EXPOSE 的端口。 entrypoint: entrypoint的做用是,把整個container變成了一個可執行的文件,這樣不可以經過替換CMD的方法來改變建立container的方式。可是能夠經過參數傳遞的方法影響到container內部 每一個Dockerfile只可以包含一個entrypoint,多個entrypoint只有最後一個有效 當定義了entrypoint之後,CMD只可以做爲參數進行傳遞 entrypoint定義方式: entrypoint ["executable","arg1","arg2"],這種定義方式下,CMD能夠經過json的方式來定義entrypoint的參數,能夠經過在運行container的時候經過指定command的方式傳遞參數 entrypoint <cmd>,看成/bin/bash -c "cmd"運行命令 ADD & COPY: 當在源代碼構建的方式下,能夠經過ADD和COPY的方式,把host上的文件或者目錄複製到image中 ADD和COPY的源必須在context路徑下 當src爲網絡URL的狀況下,ADD指令能夠把它下載到dest的指定位置,這個在任何build的方式下均可以work ADD相對COPY還有一個多的功能,可以進行自動解壓壓縮包,僅支持gzip, bzip2,xz 。 ENV: ENV key value 用來設置環境變量,後續的RUN可使用它所建立的環境變量 當建立基於該鏡像的container的時候,會自動擁有設置的環境變量 WORKDIR: 用來指定當前工做目錄(或者稱爲當前目錄) 當使用相對目錄的狀況下,採用上一個WORKDIR指定的目錄做爲基準 USER: 指定UID或者username,來決定運行RUN指令的用戶 ONBUILD: ONBUILD做爲一個trigger的標記,能夠用來trigger任何Dockerfile中的指令 能夠定義多個ONBUILD指令 當下一個鏡像B使用鏡像A做爲base的時候,在FROM A指令前,會先按照順序執行在構建A時候定義的ONBUILD指令 ONBUILD <DOCKERFILE 指令> <content> VOLUME: 用來建立一個在image以外的mount point,用來在多個container之間實現數據共享 運行使用json array的方式定義多個volume VOLUME ["/var/data1","/var/data2"] 或者plain text的狀況下定義多個VOLUME指令
[root@m01 /dockerfile/cloud]# ll 3295253 -rw-r--r-- 1 root root 1.8K 2020-02-03 19:30:52 CentOS-Base.repo 3295257 -rw-r--r-- 1 root root 332 2020-02-03 19:32:14 cloud.conf 3295260 -rw-r--r-- 1 root root 699 2020-02-03 19:35:26 dockerfile 3295255 -rw-r--r-- 1 root root 664 2020-02-03 19:30:52 epel.repo 3295258 -rwxr-xr-x 1 root root 80 2020-02-03 19:32:55 init.sh* 3295254 -rw-r--r-- 1 root root 14M 2020-02-03 19:33:14 kodexplorer4.40.zip 3295256 -rw-r--r-- 1 root root 356 2020-02-03 19:30:52 nginx.repo
[root@m01 /dockerfile/cloud]# cat dockerfile FROM centos:7 COPY CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo COPY epel.repo /etc/yum.repos.d/epel.repo COPY nginx.repo /etc/yum.repos.d/nginx.repo RUN yum install nginx php-fpm unzip php-gd php-mbstring -y \ && yum clean all && rm -rf /var/cache/yum/* RUN rm -rf /etc/nginx/conf.d/default.conf \ && sed -i '/^user/c user = nginx' /etc/php-fpm.d/www.conf \ && sed -i '/^group/c group = nginx' /etc/php-fpm.d/www.conf \ && sed -i '/daemonize/s#no#yes#g' /etc/php-fpm.conf COPY cloud.conf /etc/nginx/conf.d/cloud.conf RUN mkdir /code WORKDIR /code COPY kodexplorer4.40.zip /code/kodexplorer4.40.zip RUN unzip kodexplorer4.40.zip \ && rm -f kodexplorer4.40.zip \ && chown -R nginx:nginx . VOLUME /code COPY init.sh /init.sh EXPOSE 80 CMD ["/bin/bash","/init.sh"]
[root@m01 /dockerfile/cloud]# docker build --network=host -t centos_cloud:v1.0 . 指令最後一個 . 是上下文路徑,是指 docker 在構建鏡像,有時候想要使用到本機的文件(好比複製),docker build 命令得知這個路徑後,會將路徑下的全部內容打包。 解析:因爲 docker 的運行模式是 C/S。咱們本機是 C,docker 引擎是 S。實際的構建過程是在 docker 引擎下完成的,因此這個時候沒法用到咱們本機的文件。這就須要把咱們本機的指定目錄下的文件一塊兒打包提供給 docker 引擎使用。 若是未說明最後一個參數,那麼默認上下文路徑就是 Dockerfile 所在的位置。 注意:上下文路徑下不要放無用的文件,由於會一塊兒打包發送給 docker 引擎,若是文件過多會形成過程緩慢。 [root@m01 /dockerfile/cloud]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE centos_cloud v1.0 d3ad2a47d2a2 15 minutes ago 487MB
[root@m01 /dockerfile/cloud]# docker run -d -p 80:80 d3ad2a47d2a2 a988d966e6869cfb5fcd992cd7b7a605e8154b9493d26cd8863f5f0e986282ec