在docker中運行web服務
1 ) 以nginx爲例運行一個web服務
- 以nginx爲例,如果要運行nginx就要有一個nginx鏡像
- 在hub.docker.com中搜索nginx鏡像,可以查看到有很多版本,我們找到一個基於alpine的版本(因爲體積小,最新的體積會很大)
- $
docker pull nginx:alpine
此時我們下載好了基於alpine製作的nginx鏡像 - 如果運行這個容器:$
docker run --rm nginx:alpine
,那麼會卡住,因爲nginx會作爲一直提供服務 - 我們重新以後臺服務的方式來運行我們的nginx, $
docker run -d --rm nginx:alpine
, 此時會不佔用終端以後臺服務方式運行
2 ) 運行docker服務並暴露端口
- 我們檢查下現有的docker容器:$
docker ps
可以看到這個nginx服務佔用了80端口提供服務 - 如果直接訪問物理機的ip地址(默認80端口),是無法訪問的,因爲在容器裏是一個封閉的環境, 而我們當前機器上並沒有打開80端口
- 容器和物理機之間,兩者是隔離開的,我們先把這個nginx服務給結束掉:$
docker kill nginx對應的容器ID
- 我們需要把nginx暴露的端口映射到物理機上, $
docker run -d --rm -P nginx:alpine
, 注意這裏是大寫的P選項 - 再次查看容器, $
docker ps
, 發現輸出內容, 舉例:0.0.0.0:32768->80/tcp
, 物理機上的32768端口映射到了docker容器的80端口 - 我們通過訪問
物理機ip:32768
即可訪問docker上的容器, 我們使用-P
選項的意義就是讓物理機上一個沒有使用的端口和docker容器上的一個端口做映射 - 但是這樣同樣存在一個問題,當docker容器重新運行後,端口可能就不是32768了,可能是別的了
- 如果是這樣,沒有一個固定的端口,我們就沒法對外提供一個穩定的服務, 我們在實際應用中會使用另外一個選項
-p
,此處p是小寫,我們可以自己指定端口 - 即:$
docker run -d --rm -p 8080:80 nginx:alpine
, 我們將物理機的8080端口綁定容器的80端口,這樣的話就不會發生錯亂的情況了 - 容器與容器之間的端口互不影響,它們之間都是隔離開的
- 我們查詢docker容器可以使用
-q
的方式, 如:$docker ps -q
, 輸出運行容器的ID列表 - 我們就可以通過 $
docker kill $(docker ps -q)
將所有運行中的容器全部關閉
構建自己的docker鏡像
- 在docker中使用$
docker build
來構建一個docker鏡像 - 在構建鏡像前,我們需要先編寫dockerfile文件來構建新的鏡像
- 查閱docker的官方文檔: https://docs.docker.com/engine/reference/builder/
- 查看右側幾個主要的命令:
FROM
、RUN
、CMD
、LABEL
、COPY
、WORKDIR
FROM
: 表示指定基礎鏡像RUN
: 在構建過程中需要執行的命令CMD
: 用於容器啓動時需要執行的命令LABEL
: 標籤,用於添加擴展的信息到鏡像中, 如版本信息, 維護者信息等COPY
: 用於將文件拷貝到鏡像之中WORKDIR
: 用於設置命令的工作目錄- 我們編輯一個Dockerfile, $
vi Dockerfile
# 基於ubuntu,體積較大 # FROM ubuntu:16.04 FROM alpine LABEL version="1.0" LABEL description="my image" # 基於ubuntu的安裝命令 # RUN apt update && apt -y install python3 # 基於alpine的安裝命令, 儘量把所有命令都寫到一起, 使用&&來連接, 避免多餘的命令分層 RUN apk update && apk add python3 # 將當前目錄下的所有文件拷貝到容器裏的code目錄,. 代表當前目錄 COPY . /code # 指定工作目錄 WORKDIR /code # 指定容器啓動後將要執行的命令 CMD ["python3", "app.py"]
- 在同一目錄下, 我們編寫一個python文件
app.py
print("Hello Python")
- 開始構建一個新的鏡像, $
docker build -t myapp .
-t
是--tag
的縮寫.
是當前目錄, dockerfile就在當前目錄
- 構建完畢後, 可以通過 $
docker images
來查看,看到多了一個鏡像myapp
- 我們開始運行這個鏡像, $
docker run --rm myapp
, 輸出Hello Python
- 在通過鏡像啓動容器的時候,有時候會在後面跟上一個命令,如: $
docker run --rm myapp echo hi
- 這裏
echo hi
等價於在dockerfile中的CMD中的內容,並且會覆蓋CMD中的命令 - 此時會輸出
hi
,而非Hello Python
- 這裏
- 在已經構建好的鏡像中,查看詳細信息 $
docker inspect myapp:latest
, 可以查看到鏡像中更多的詳細信息"Labels" : { "description" : "my image", "version": "1.0" }, "Cmd" : [ "python3", "app.py" ], "WorkingDir": "/code", # ... # 不再列舉
- 在構建我們鏡像的時候,最好使用默認的
Dockerfile
, 如果不這樣做, 在docker build
的時候需要使用--file
來指定文件名