目錄html
給你的環境作一個快速運行測試,以確保你已經準備好了python
docker run hello-world
如今到了以docker的方式去構建一個應用了。咱們從整個應用的架構的底層開始,這裏是一個容器,咱們會在本頁介紹它。在此層級之上是一個服務,它定義了容器在生產環境中會如何工做,咱們會在第三部分介紹。最後,最頂層的是堆棧,定義全部服務的交互行爲,咱們會在第五部分介紹。web
在過去,若是你要寫一個ptyhon應用,首先你要在你的機器上安裝一套ptyhon的運行環境。可是,這就產生了一種狀況,爲了讓你的應用按照預期運行,你機器上的環境須要精確部署,並且還須要和你的生產環境相匹配。
使用Dcoker,你只須要將一個便攜的python運行時(就是一套可執行的python)做爲鏡像,而沒有安裝的必要。而後,你構建的鏡像能夠包括基本的Python鏡像和你的應用代碼。以確保你的應用、應用的依賴和運行環境所有在一塊兒。
這些由某些內容定義的便攜的鏡像叫作 Dockerfile
。redis
Dockerfile
定義一個容器Dockerfile
定義容器內環境中的內容。對注入網絡接口和磁盤驅動的訪問都在這個環境中被虛擬化。以和系統的其他部分分離開來,所以你須要將端口映射到外部,並具體指明你想要將什麼文件「複製到」該環境。docker
對諸如網絡接口和磁盤驅動器等資源的訪問在這個環境中被虛擬化, 這與系統的其他部分隔離開來, 所以您須要將端口映射到外部世界, 並具體要 "複製" 哪些文件到該環境。無論怎樣,能夠保證在這個 Dockerfile
中構建定義的應用能夠在任何地方均可以同樣的運行。shell
Dockerfile
建立一個空目錄。進入該目錄,並建立一個名爲 Dockerfile
的文件,把如下內容複製粘貼到該文件中,並保存。注意dockerfile文件中解釋每一條語句的註釋內容。json
# Use an official Python runtime as a parent image FROM python:2.7-slim # Set the working directory to /app WORKDIR /app # Copy the current directory contents into the container at /app ADD . /app # Install any needed packages specified in requirements.txt RUN pip install --trusted-host pypi.python.org -r requirements.txt # Make port 80 available to the world outside this container EXPOSE 80 # Define environment variable ENV NAME World # Run app.py when the container launches CMD ["python", "app.py"]
這個 Dockerfile
文件引用了咱們尚未建立的文件,app.py
和 requirements.txt
。 稍後咱們會建立它們。flask
再建立兩個文件,app.py
和 requirements.txt
,並把他們放入和 Dcokerfile
相同的目錄裏。這樣咱們就完成了應用,你能夠看到,這很簡單。當上面的 Dcokerfile
被構建到一個鏡像中時,app.py
和 requirements.txt
也會存在於這個鏡像,這是由於 Dockerfile
有 ADD
命令,而且由於有 EXPOSE
命令, app.py
的輸出能夠經過 HTTP 訪問。windows
requirements.txt
Flask Redis
app.py
from flask import Flask from redis import Redis, RedisError import os import socket # Connect to Redis redis = Redis(host="redis", db=0, socket_connect_timeout=2, socket_timeout=2) app = Flask(__name__) @app.route("/") def hello(): try: visits = redis.incr("counter") except RedisError: visits = "<i>cannot connect to Redis, counter disabled</i>" html = "<h3>Hello {name}!</h3>" \ "<b>Hostname:</b> {hostname}<br/>" \ "<b>Visits:</b> {visits}" return html.format(name=os.getenv("NAME", "world"), hostname=socket.gethostname(), visits=visits) if __name__ == "__main__": app.run(host='0.0.0.0', port=80)
如今咱們看到 pip install -r requirements.txt
爲 Python 安裝了Flask 和Redis庫,應用程序打印了環境變量NAME
,以及調用socket.gethostname()
後的輸出。最終,由於Redis沒有運行(咱們只安裝了Python庫,沒有安裝redis),正常的話,咱們能夠看到嘗試使用redis失敗,產生的錯誤信息。瀏覽器
注意:當在容器內部檢索容器ID時,訪問的主機名就像一個正在運行的進程的ID
就是這樣,你的系統中不須要 python 或 requirements.txt
中的任何內容,構建和運行這個鏡像時也不須要在你的系統上安裝它們。看起來你並無安裝Python和Flask的環境,但你已經有了。
咱們已經準備好了去構建應用。確保你一直都在新建目錄的最上級。你能夠看到以下內容:
$ ls Dockerfile app.py requirements.txt
如今運行構建命令,這會建立一個Docker鏡像,咱們可使用 -t
參數給它指定一個友好的名字。
docker build -t friendlyhello .
構建的鏡像保存在哪裏呢?鏡像會保存在你機器上本地的Docker鏡像registry裏:
$ docker image ls REPOSITORY TAG IMAGE ID friendlyhello latest 326387cea398
Linux用戶故障排查
代理服務器設置
代理服務器啓動運行後,能夠阻塞與web應用的連接。若是你使用了代理服務器,把下面的內容添加到你的Dockerfile,使用ENV
命令指定你的代理服務器的主機和端口:
# Set proxy server, replace host:port with values for your servers ENV http_proxy host:port ENV https_proxy host:port
DNS設置
DNS配置錯誤能夠致使使用pip
時出現問題。你須要設置你本身的DNS服務器地址來pip
正常工做。可能你想修改 Docker守護進程的DNS設置,你能夠編輯(或建立)配置文件/etc/docker/daemon.json
,設置 dns關鍵字,內容以下:
{ "dns": ["your_dns_address", "8.8.8.8"] }
上面的例子中,列表的第一個元素是DNS服務器的地址,第二個是Google的DNS,當第一個地址沒法使用時,會使用第二個。
在繼續以前,先保存daemon.json
並重啓docker服務。
sudo service docker restart
問題修復後,從新嘗試build
命令
運行應用,使用-p
參數將你的機器的4000端口映射到容器的發佈端口80上。
docker run -p 4000:80 friendlyhello
你會在http://0.0.0.0:80看到一個Pyhton正常爲你的應用服務的消息。可是這個消息來自容器內部,它不知道你將該容器的80端口映射到4000端口,須要輸入正確的URL http://localhost:4000
。
在瀏覽器中訪問正確的URL,以查看網頁中顯示的內容。
注意:若是你在Windows7中使用Docker Toolbox,要使用Docker機器的IP替換
localhost
。例如,http://192.168.99.100:4000/。使用docker-machine ip
命令能夠找到這個IP地址。
你也能夠在shell中使用curl
命令看到相同的內容。
$ curl http://localhost:4000 <h3>Hello World!</h3><b>Hostname:</b> 8fc990912a14<br/><b>Visits:</b> <i>cannot connect to Redis, counter disabled</i>
這裏從新映射 4000:80
演示了和 Dockerfiile
中EXPOSE
的不一樣之處,並且在運行 docker run -p
時設置了發佈的值。在後面的步驟中,映射了主機的4000端口到容器的80端口,並使用了 http://localhost
。
在你的終端中使用 CTRL+C
來退出。
在Windows中,顯示的關閉容器
在windows系統,CTRL+C
不會關閉容器。因此,首先輸入CTRL+C
返回提示符(或者新打開一個shell),而後輸入docker container ls
來列出運行中的容器,隨後經過docker container stop <Container NAME or ID>
來關閉容器。不然,在稍後的步驟中,當你嘗試從新運行容器會獲得一個來自守護進程錯誤的響應。
如今咱們以分離模式在後臺運行應用:
docker run -d -p 4000:80 friendlyhello
你會得到應用容器的長ID並返回終端,容器會在後臺運行,你還能夠榮國 docker container ls
查看縮寫的容器ID()
$ docker container ls CONTAINER ID IMAGE COMMAND CREATED 1fa4ab2cf395 friendlyhello "python app.py" 28 seconds ago
注意 容器ID
與 http://localhost:4000
上的內容相匹配。
如今使用 docker container stop
指定 容器ID
來結束進程,以下:
docker container stop 1fa4ab2cf395
爲了證實咱們剛剛建立的鏡像的可移植性,咱們能夠上傳構建的鏡像並在任何地方運行它。畢竟,當你想把容器部署到生產環境中時,你須要知道如何推送到 registries。
一個registry 是一個倉庫的集合,一個倉庫是一個鏡像的集合——相似於GitHub的倉庫。只是代碼已經構建好了。registry上的一個用戶能夠建立多個倉庫。docker
CLI默認使用Docker的公共registry。
注意: 這裏咱們使用Docker的公共registry是由於它是免費的和預置的,不過咱們仍是有不少公共的registry能夠選擇,甚至你可使用
Docker Trusted Registry
來搭建你本身私有的registry。
若是你沒有docker用戶,能夠在hub.docker.com註冊一個。記下你的用戶名。在你的本地機器上登陸到DOcker公共的registry。
$ docker login
關聯本地鏡像與registry倉庫的方法是 username/repository:tag
。標籤是可選的,但建議設置上,由於這是registry爲docekr鏡像提供版本的機制,根據上下文給倉庫和標籤起一個有意義的名字,例如:get-started:part2
。這裏咱們將鏡像放在 get-started
倉庫,標籤名字爲 part2
。
如今,把它們放在一塊兒來標記鏡像。使用in的用戶名、倉庫和標籤名來運行 docker tag image
,以便將鏡像上傳到你想要上傳的位置,命令語法以下:
docker tag image username/repository:tag
例如:
docker tag friendlyhello gordon/get-started:part2
運行docker image ls
來查看你信打標籤的鏡像:
$ docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE friendlyhello latest d9e555c53008 3 minutes ago 195MB gordon/get-started part2 d9e555c53008 3 minutes ago 195MB python 2.7-slim 1c7128a655f6 5 days ago 183MB ...
把打過標籤的鏡像上傳到倉庫:
docker push username/repository:tag
完成以後,上傳之的鏡像會被公開發布。若是你登陸到了 Docker Hub,你可使用pull命令,在Docker Hub看到最新的鏡像。
從如今開始,你能夠在在任何機器上使用docker run
運行你的應用:
docker run -p 4000:80 username/repository:tag
若是鏡像在本地機器上不可用,Docker會從遠程倉庫上拉取鏡像:
$ docker run -p 4000:80 gordon/get-started:part2 Unable to find image 'gordon/get-started:part2' locally part2: Pulling from gordon/get-started 10a267c67f42: Already exists f68a39a6a5e4: Already exists 9beaffc0cf19: Already exists 3c1fe835fb6b: Already exists 4c9f1fa8fcb8: Already exists ee7d8f576a14: Already exists fbccdcced46e: Already exists Digest: sha256:0601c866aab2adcc6498200efd0f754037e909e5fd42069adeff72d1e2439068 Status: Downloaded newer image for gordon/get-started:part2 * Running on http://0.0.0.0:80/ (Press CTRL+C to quit)
如今不管你在哪裏運行docker run
,他會拉取鏡像,Pyhton、requirements.txt
中指定的依賴和你的代碼 會在一塊兒運行,他們所有打包在一個小包裹裏(鏡像),你不須要在你的機器上安裝任何東西,Docker 就能夠運行它了。
這就是本頁全部內容,下一節,咱們會經過在服務中運行這個容器來學習如何擴展咱們的應用程序。
官方在這裏提供了一段視頻,但我這裏觀看有問題,我就找把視頻錄製下來放到了B站,地址以下:
B站的「分享視頻」中給的代碼放在博客園沒法播放,只能在這裏寫一個地址了。
下面是本頁中關於docker的基本命令列表,以及一些相關的命令,在繼續後面的學習前能夠研究一下。
docker build -t friendlyhello . # Create image using this directory's Dockerfile docker run -p 4000:80 friendlyhello # Run "friendlyname" mapping port 4000 to 80 docker run -d -p 4000:80 friendlyhello # Same thing, but in detached mode docker container ls # List all running containers docker container ls -a # List all containers, even those not running docker container stop <hash> # Gracefully stop the specified container docker container kill <hash> # Force shutdown of the specified container docker container rm <hash> # Remove specified container from this machine docker container rm $(docker container ls -a -q) # Remove all containers docker image ls -a # List all images on this machine docker image rm <image id> # Remove specified image from this machine docker image rm $(docker image ls -a -q) # Remove all images from this machine docker login # Log in this CLI session using your Docker credentials docker tag <image> username/repository:tag # Tag <image> for upload to registry docker push username/repository:tag # Upload tagged image to registry docker run username/repository:tag # Run image from a registry