一文講明白Docker是什么 docker是干什么的


一文講明白Docker是什么 docker是干什么的

文章插圖
Java識堂 , 一個高原創,高收藏 , 有干貨的微信公眾號,一起成長,一起進步 , 歡迎關注
Docker是什么?Docker是一個基于輕量級虛擬化技術的容器,整個項目基于Go語言開發,并采用了Apache 2.0協議 。Docker可以將我們的應用程序打包封裝到一個容器中,該容器包含了應用程序的代碼、運行環境、依賴庫、配置文件等必需的資源,通過容器就可以實現方便快速并且與平臺解耦的自動化部署方式,無論你部署時的環境如何,容器中的應用程序都會運行在同一種環境下 。
舉個栗子 , 小明寫了一個CMS系統,該系統的技術棧非常廣 , 需要依賴于各種開源庫和中間件 。如果按照純手動的部署方式,小明需要安裝各種開源軟件,還需要寫好每個開源軟件的配置文件 。如果只是部署一次 , 這點時間開銷還是可以接受的 , 但如果小明每隔幾天就需要換個服務器去部署他的程序,那么這些繁瑣的重復工作無疑是會令人發狂的 。這時候,Docker的用處就派上場了,小明只需要根據應用程序的部署步驟編寫一份Dockerfile文件(將安裝、配置等操作交由Docker自動化處理),然后構建并發布他的鏡像,這樣,不管在什么機器上,小明都只需要拉取他需要的鏡像,然后就可以直接部署運行了,這正是Docker的魅力所在 。
那么鏡像又是什么呢?鏡像是Docker中的一個重要概念:
  • Image(鏡像):它類似于虛擬機中使用到的鏡像 , 由于任何應用程序都需要有它自己的運行環境,Image就是用來提供所需運行環境的一個模板 。
  • Container(容器):Container是Docker提供的一個抽象層,它就像一個輕量級的沙盒,其中包含了一個極簡的Linux系統環境與運行在其中的應用程序 。Container是Image的運行實例(Image本身是只讀的,Container啟動時,Docker會在Image的上層創建一個可寫層,任何在Container中的修改都不會影響到Image , 如果想要在Image保存Container中的修改,Docker采用了基于Container生成新的Image層的策略),Docker引擎利用Container來操作并隔離每個應用(也就是說,每個容器中的應用都是互相獨立的) 。
其實從Docker與Container的英文單詞原意中就可以體會出Docker的思想 。Container可以釋義為集裝箱,集裝箱是一個可以便于機械設備裝卸的封裝貨物的通用標準規格,它的發明簡化了物流運輸的機械化過程 , 使其建立起了一套標準化的物流運輸體系 。而Docker的意思為碼頭工人 , 可以認為,Docker就像是在碼頭上辛勤工作的工人,把應用打包成一個個具有某種標準化規格的"集裝箱"(其實這里指出的集裝箱對應的是Image,在Docker中Container更像是一個運行中的沙盒),當貨物運輸到目的地后,碼頭工人們(Docker)就可以把集裝箱拆開取出其中的貨物(基于Image來創建Container并運行) 。這種標準化與隔離性可以很方便地組合使用多個Image來構建你的應用環境(Docker也提倡每個Image都遵循單一職責原則,也就是只做好一件事),或者與其他人共享你的Image 。
本文作者為SylvanasSun(sylvanas.sun@gmail.com),首發于SylvanasSun’s Blog 。
原文鏈接:sylvanassun.github.io/2017/11/19/…
(轉載請務必保留本段聲明,并且保留超鏈接 。)
Docker VS 虛擬機在上文中我們提到了Docker是基于輕量級虛擬化技術的,所以它與我們平常使用的虛擬機是不一樣的 。虛擬機技術可以分成以下兩類:
一文講明白Docker是什么 docker是干什么的

文章插圖
系統虛擬機
  • 系統虛擬機:通過軟件對計算機系統的模擬來提供一個真實計算機的替代品 。它是物理硬件的抽象并提供了運行完整操作系統所需的功能 。虛擬機通過物理機器來管理和共享硬件,這樣實現了多個虛擬機環境彼此之間的隔離,一臺機器上可以運行多個虛擬機,每個虛擬機包括一個操作系統的完整副本 。在系統虛擬機中,所運行的所有軟件或操作都只會影響到該虛擬機的環境 。我們經常使用的VMWare就是系統虛擬機的實現 。
  • 程序虛擬機:允許程序獨立運行在平臺之外 。比較典型的例子就是JVM , Java通過JVM這一抽象層使得Java程序與操作系統和硬件平臺解耦(因為每個Java程序都是運行在JVM中的),因此實現了所謂的compile once, run everywhere 。
Docker所用到的技術與上述兩種都不相同,它使用了更輕量級的虛擬化技術,多個Container共享了同一個操作系統內核 , 并且就像運行在本地上一樣 。Container技術相對于虛擬機來說,只是一個應用程序層的抽象,它將代碼與依賴關系打包到一起,多個Container可以在同一臺機器上運行(意味著一個虛擬機上也可以運行多個Container),并與其它Container共享操作系統內核 , 每一個Container都在用戶空間中作為一個獨立的進程運行,這些特性都證明了Container要比虛擬機更加靈活與輕量(一般都是結合虛擬機與Docker一起使用) 。
一文講明白Docker是什么 docker是干什么的

文章插圖
Container技術其實并不是個新鮮事物 , 最早可以追溯到UNIX中的chroot(在1979年的V7 Unix中引入),它可以改變當前正在運行的進程及其子目錄的根目錄,在這種修改過的環境下運行的程序不能在指定的目錄樹之外訪問文件,從而限制用戶的活動范圍 , 為進程提供了隔離空間 。
之后各種Unix版本涌現出很多Container技術,在2006年,Google提出了"Process Containers"期望在Linux內核中實現進程資源隔離的相關特性,由于Container在Linux內核中的定義過于寬泛混亂,后來該項目改名為CGroups(Control Groups),實現了對進程的資源限制 。
2008年,LXC(Linux Containers)發布,它是一種在操作系統層級上的虛擬化方法,用于在Linux系統上通過共享一個內核來運行多個互相隔離的程序(Container) 。LXC正是結合了Linux內核中的CGroups和對分離的名稱空間的支持來為應用程序提供了一個隔離的環境 。而Docker也是基于LXC實現的(Docker的前身是dotClound公司中的內部項目,它是一家提供PaaS服務的公司 。),并作出了許多改進 。
使用Docker在使用Docker之前你需要先安裝Docker(這好像是一句廢話 。。。),根據不同的平臺安裝方法都不相同 , 可以去參考Install Docker | Docker Documentation或者自行Google 。
安裝完畢之后,輸入docker --version來確認是否安裝成功 。
$ docker --versionDocker version 17.05.0-ce-rc1, build 2878a85復制代碼從Docker Hub中可以pull到其他人發布的Image,我們也可以注冊一個賬號去發布自己的Image與他人共享 。
[root@Jack ~]# docker search redis # 查看redis鏡像是否存在[root@Jack ~]# docker pull redis # 拉取redis鏡像到本機Using default tag: latestTrying to pull repository docker.io/library/redis ... latest: Pulling from docker.io/library/redisDigest: sha256:cd277716dbff2c0211c8366687d275d2b53112fecbf9d6c86e9853edb0900956[root@Jack ~]# docker images # 查看鏡像信息REPOSITORY TAG IMAGE ID CREATED SIZEdocker.io/python 3.6-onbuild 7195f9298ffb 2 weeks ago 691.1 MBdocker.io/mongo latest d22888af0ce0 2 weeks ago 360.9 MBdocker.io/redis latest 8f2e175b3bd1 2 weeks ago 106.6 MB復制代碼有了Image,之后就可以在其之上運行一個Container了 , 命令如下 。
[root@Jack ~]# docker run -d -p 6379:6379 redis # 運行redis,-p代表將本機上6379端口映射到Container的6379端口 -d代表在后臺啟動[root@Jack ~]# docker ps -a # 查看容器信息 , 如果不加-a只會顯示當前運行中的容器# 如果想要進入容器中,那么需要執行以下命令[root@Jack ~]# docker ps # 先獲得容器的idCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES1f928073b7eb redis "docker-entrypoint.sh" 45 seconds ago Up 44 seconds 0.0.0.0:6379->6379/tcp desperate_khorana[root@Jack ~]# docker exec -it 1f928073b7eb /bin/bash # 然后再執行該命令進入到容器中root@1f928073b7eb:/data# touch hello_docker.txt # 在容器中創建一個文件root@1f928073b7eb:/data# exit # 退出exit[root@Jack ~]# # 也可以在啟動時直接進入 命令如下[root@Jack ~]# docker run -d -it -p 6379:6379 redis /bin/bash復制代碼【一文講明白Docker是什么 docker是干什么的】我們對Container做出了修改,如果想要保留這個修改 , 可以通過commit命令來生成一個新的Image 。
# -m為描述信息 -a為作者 1f9是你要保存的容器id 取前3個字符 docker可以自行識別# sylvanassun/redis為鏡像名 :test 為一個tag 一般用于標識版本[root@Jack ~]# docker commit -m "test" -a "SylvanasSun" 1f9 sylvanassun/redis:testsha256:e7073e8e5bd70b8d58092fd6bd8c2551e65dd29241c235eddf2a7f4b4b25cbbd[root@Jack ~]# docker imagesREPOSITORY TAG IMAGE ID CREATED SIZEsylvanassun/redis test e7073e8e5bd7 2 seconds ago 106.6 MBdocker.io/python 3.6-onbuild 7195f9298ffb 2 weeks ago 691.1 MBdocker.io/mongo latest d22888af0ce0 2 weeks ago 360.9 MBdocker.io/redis latest 8f2e175b3bd1 2 weeks ago 106.6 MB復制代碼想刪除一個容器或鏡像也很簡單,但在刪除鏡像前需要先刪除依賴于它的容器 。
[root@Jack ~]# docker stop 1f9 # 關閉運行中的容器,相應的也有docker start id命令來啟動一個容器1f9[root@Jack ~]# docker rm 1f9 # 刪除容器1f9[root@Jack ~]# docker rmi e70 # 刪除上面保存的鏡像Untagged: sylvanassun/redis:testDeleted: sha256:e7073e8e5bd70b8d58092fd6bd8c2551e65dd29241c235eddf2a7f4b4b25cbbdDeleted: sha256:751db4a870e5f703082b31c1614a19c86e0c967334a61f5d22b2511072aef56d復制代碼如果想要自己構建一個鏡像,那么需要編寫Dockerfile文件 , 該文件描述了鏡像的依賴環境以及如何配置你的應用環境 。
# 使用python:2.7-slim 作為父鏡像FROM python:2.7-slim# 跳轉到/app 其實就是cd命令WORKDIR /app# 將當前目錄的內容(.)復制到鏡像的/app目錄下ADD . /app# RUN代表運行的shell命令,下面這條命令是根據requirements.txt安裝python應用的依賴包RUN pip install --trusted-host pypi.python.org -r requirements.txt# 暴露80端口讓外界訪問EXPOSE 80# 定義環境變量ENV NAME World# 當容器啟動時執行的命令,它與RUN不同,只在容器啟動時執行一次CMD ["python", "app.py"]復制代碼然后就可以通過docker build -t xxx/xxxx .命令來構建鏡像,-t后面是鏡像名與tag等信息,注意.表示在當前目錄下尋找Dockerfile文件 。
學會如何構建自己的鏡像之后,你是否也想將它發布到Docker Hub上與他人分享呢?要想做到這一點 , 需要先注冊一個Docker Hub賬號,之后通過docker login命令登錄,然后再docker push image name , 就像在使用Git一樣簡單 。
關于Docker的更多命令與使用方法,請參考Docker Documentation | Docker Documentation,另外我還推薦使用Docker Compose來構建鏡像,它可以很方便地組合管理多個鏡像 。
結語Docker提供了非常強大的自動化部署方式與靈活性 , 對多個應用程序之間做到了解耦,提供了開發上的敏捷性、可控性以及可移植性 。同時,Docker也在不斷地幫助越來越多的企業實現了向云端遷移、向微服務轉型以及向DevOps模式的實踐 。
如今 , 微服務與DevOps火爆程度日益漸高,你又有何理由選擇拒絕Docker呢?讓我們一起選擇擁抱Docker,擁抱未來!
作者:SylvanasSun鏈接:https://juejin.im/post/5a11710ef265da432002d689