【学习笔记】Docker - 02. 在容器中运行软件(上)
2.1?控制容器:?構建一個網站監視器?
需求:?客戶想讓你做一個網站,?這個網站需要被緊密的監視,?如果服務器宕機了,?那么它們的團隊會收到相關的郵件.?
這里用到了3個容器.?第一個運行NGINX;?第二個運行一個叫做mailer的程序.?這兩個容器都是detached的.?
Detached?表示容器將在后臺運行,?不會附加到任何的輸入或者是輸出流上面.?
第三個容器,?叫做代理,?將會運行在一個交戶的容器內?
?
2.1.1?創建并開始一個容器?
Docker把運行一個程序所需要的那些文件和指令叫做鏡像. 當我們使用Docker安裝軟件的時候, 我們實際上是在使用Docker下載或創建容器. Docker鏡像包含了一臺電腦要運行某個軟件所需的所有東西.?
?
從Docker Hub下載NGINX鏡像.??
Docker Hub是Docker 公司提供的公共注冊中心, 而NGINX是一個可信的倉庫.?
?
運行下面的命令將會下載, 安裝, 和開始一個運行著NGINX的容器:?
docker run --detach --name web nginx:latest?
當你運行這個命令的時候, Docker會從NGINX倉庫安裝nginx:latest這個版本的鏡像, 而NGINX倉庫則是在Docker Hub上面托管的, 然后會立即運行這個軟件.?
?
運行起來之后, 在終端上將會出現類似這樣的隨機字符串:?
7cb5d2b9a7eab87f07182b5bf58936c9947890995b1b94f412912fa822a9ecb5?
這堆字符串是容器的唯一標識符, 每次你使用docker run并創建一個新容器的時候, 它都會得到一個唯一標識符.?
?
標識符顯示出來之后, 好像什么也沒發生, 這是因為你使用?--detach?這個參數, 它會讓你的程序在后臺運行. 這就是意味著你的程序已經啟動了, 但是沒有附加到你的終端上. 像類似NGINX這樣的服務器軟件通常都不需要附加在終端上的, 所以通常都是運行在detached的容器里.?
?
對于那些在后臺安靜運行的程序來說, 運行detached的容器是再合適不過的了. 這類程序通常叫做daemon(守護進程)或服務. 守護進程通常會通過網絡或其他通信渠道來和其它程序或人類交互. 當你想要在容器里的后臺運行daemon或其他程序的時候, 就需要使用 --detach 這個flag, 簡寫是?-d.?
?
本例中另一個daemon是mailer(郵件程序), mailer會等待調用者發起連接, 然后發送一個郵件.?
安裝和運行mailer的命令:?
docker run -d --name mailer dockerinaction/ch2_mailer?
?
2.1.2?運行交互式的容器?
例如, 基于終端的文本編輯器就是需要附加終端的程序. 它通過鍵盤等設備得到輸入, 并把輸出顯式在終端上. 所以在它的輸入輸出流上, 它是可交互的.?
開始使用交互式的容器:?
docker run --interactive --tty \?
???? --link web:web \?
???? --name web_test \?
???? busybox:1.29 /bin/sh?
針對run命令, 這里用到了兩個flag:?
--interactive (簡寫是 -i). 這個選項告訴Docker讓標準輸入流(stdin)為容器保持打開, 即使沒有終端被附加上.?
--tty (-t). 它會告訴Docker為容器分配一個虛擬終端, 你就可以通過這個終端來傳遞指令給容器.?
針對交互式的程序, 這兩個flag通常一起使用.?
?
和交互式的flags一樣重要, 當你啟動容器的時候, 你指定了一個在容器內要運行的程序. 本例中就是一個shell程序叫做sh.?
?
這段命令最終創建了一個容器, 開啟了一個UNIX shell, 并且鏈接到了運行NGINX的容器. 從shell里, 你可以運行一個命令來驗證你的web server是否正常運行:?
wget -O -?http://web:80/?
如果得到以下結果,?那么就是成功了:?
想要關閉交互式容器的話,?你可以輸入?exit.?這就會終止shell程序并且停止容器.?
?
也可以創建一個交互式容器,?手動在容器里開始一個進程,?然后detach你的終端.?這就需要按住Ctrl和P鍵,?然后松開P鍵去按Q鍵.?但是只有你使用--tty這個參數的時候,?它才會起作用.?
?
2.1.3?列出,?停止,?重啟容器以及查看容器的輸出.??
使用docker ps命令來查看正在運行等容器.?
運行該命令后,?針對每個運行的容器,?將會顯示以下信息:?
容器的ID?
用了哪個鏡像?
容器內執行了的命令?
自從容器建立以來經過的時間?
程序運行了多久?
容器暴露的網絡端口?
容器的名字?
現在,?你應該有三個容器了,?名字分別是web, mailer?和?agent.?
?
重啟容器:?docker restart xxx?
例如:??
docker restart web?
docker restart mailer?
docker restart agent?
?
查看容器的日志:?docker logs xxx?
例如:?
docker logs web?
如果過于依賴docker logs,?那么可能會有危險.?因為任何程序寫入到stdout或stderr輸出流的東西將會在這個log里面被記錄.?這種模式的缺點是log在默認情況下不會循環或截斷,?所以容器寫入到log的數據將會和容器一起一直保留.?對于長存的進程,?這種長期的持久化可能會是個問題.?更好處理log數據的方式是使用卷(volumes).?
docker logs?命令也有flag參數, --follow或-f,?加上它之后就會在顯示出當前日志的同時并繼續監視如果有新的日日志,?那么就更新顯示的日志.?當你不想看的時候,?就按Ctrl + C?終端logs命令即可?
?
停止容器中PID為1的程序(停止容器):?docker stop xxx?
例如: docker stop web?
?
2.2?解決問題?與?PID命名空間?
在Linux上每一個運行的程序或者叫進程都有一個唯一的數字叫做進程標識符(PID).?
PID命名空間就是一套唯一的數字,?它們可以識別出不同的進程.?
Linux提供了可以創建多個PID命名空間的工具.??
每個命名空間都有一整套可能的PID.?
這就意味著每個PID命名空間都會包含它自己的PID 1,2,3….?
?
大多數程序都不需要訪問其他正在運行的進程,?也不需要列出系統中其他正在運行的進程.??
所以?Docker默認會為每個容器創建新的PID命名空間.?一個容器的PID命名空間會把這個容器的進程與其它容器的進程隔離開.?
?
從容器內一個擁有自己命名空間的進程的角度來看, PID 1?可能是指初始化系統的進程,?例如runit或supervisord.在不同的容器, PID 1也許是指像bash一樣的命令行shell.?
執行結果分別是:?
?
?
在這個例子里,?你使用了?docker exec?命令在容器里運行額外的進程.?
這里的ps命令,?它會顯示出所有運行的進程和它們的PID.?
?
和大多數Docker隔離特性一樣,?你可以選擇不使用它們的PID命名空間來創建容器.?如果你正在使用某個程序來執行系統管理任務,?并且這項工作需要從容器內列舉出進程,?那么這點就很重要.?
你可以在docker create?或?docker run?命令上設定?--pid flag的值為host,?這樣的話,?就可以實現以上需求了.?
???
假設你沒有使用Docker,?而是直接在你的機器上運行NGINX.?假設你把這件事忘記了,?并且又開啟了一遍NGINX,?那么這第二個進程就無法訪問它需要的資源,?因為第一個進程已經擁有它們了.?這就是軟件沖突的例子.?你可以試試:?
結果是:?
第二個進程啟動失敗,?并且報告說它需要的地址已經在使用.?這叫做端口沖突.?
?
然而Docker可以簡化并解決這個問題:?
所以,?環境獨立性可以讓依賴于稀缺系統資源的軟件能自由的配置,?而且無需考慮本地其它軟件的沖突需求.?
?
下面是一些常見的沖突問題:?
兩個程序想綁定同一個網絡端口?
兩個程序使用同樣的臨時文件名, 而且文件別鎖了以防止發生這樣的事?
兩個程序使用不同版本的全局安裝的庫?
兩個進程想使用相同的PID文件?
后安裝的程序修改了另一個程序使用的環境變量, 然后第一個程序崩潰了?
多個進程搶CPU或內存資源.?
當一個或多個程序擁有共同依賴并且無法協商共享或需求不同的時候, 這些沖突就會出現.?
?
而Docker通過Linux命名空間,?資源限制,?文件系統root?和?虛擬化網絡組件等這些工具, 就解決了這些軟件的沖突. 所有的這些工具都是被用來在Docker容器內進行軟件隔離的.?
總結
以上是生活随笔為你收集整理的【学习笔记】Docker - 02. 在容器中运行软件(上)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ASP.NET Core on K8S深
- 下一篇: 今天,全网曝光这几个公众号