Docker使用心得與爬坑記錄

爲了搭建Scrapy-Redis服務而反覆地被Docker折麼了數天,終於對於Docker的使用有了一些理解,本文記錄初用Docker的一些注意事項。
一些理解可能不夠準確,望指正。

1.爲什麼要使用Docker

下面是兩個我遇到需要使用Docker的典型情景:

  • 情景1:安裝配置數據庫等服務

    • 非Docker:拿數據庫舉例,如果我們需要一個Mysql、Redis或Mongodb數據庫,配過環境的同學都知道,該過程往往需要下載安裝包、解壓、編譯、配置設置文件等過程。這些過程往往會被一些錯誤或時間過早的博文誤導而導致環境配置失敗。且如果一步做錯,想要重新卸載乾淨再重新安裝時,往往會因爲遺留問題而導致重裝失敗。
    • Docker:兩行代碼安裝運行一切數據庫,基本不需要考慮環境配置問題,因爲Docker中的容器基本都是配置好的,直接可以用於生產的。且可以很方便地開多個容器(多個數據庫),刪除重裝的操作也很簡單。
  • 情景2:安裝配置自己的應用

    • 非Docker:以部署Scrapy-Redis分佈式爬蟲框架爲例。在單機下需要安裝Scrapy、安裝Scrapy-Redis,需要配置很多Python包,需要運行Scrapyd服務。在單機搭建完成後,如果想把這一切都重新在第二個服務器上部署,麻煩且難免會出現一些問題。
    • Docker:把配置好的單機環境打包成Docker容器,在其他服務器上下載容器即可。不僅方便、快捷,最重要的是可以保證各個結點的一致性。

2. Docker容器是如何存在的?

我曾不明白爲何Docker既可以拉一個ubuntu系統,又可以拉一個mysql數據庫,或者說可以拉任何應用。
這個問題我是這樣理解的(這裏沒有特別認真地查詢資料,待指正):Docker可以製作任何可以運行在linux系統中的應用。事實上,如果我們製作一個mysql數據庫鏡像,也是需要指定一個linux系統版本:通常是ubuntu。我們使用docker pull mysql拉取下來的mysql,如果我們用docker exec -it mysql bash以bash進入該容器的話,也可以發現這就是一個ubuntu系統,我們可以用apt-get update升級,之後可以用apt-get install vim安裝文本編輯器vim。


3. Docker和虛擬機的區別?

很多文章如: Docker與虛擬機的簡介以及比較 已指出Docker與虛擬機在架構、量級與安全性等方面的差異。我的理解是:

  1. Docker更加適合於應用的部署
  2. 虛擬機更適合作爲服務器

因此,如果需要搭建一個分佈式的服務,之前的做法是用多臺服務器來做分佈式。如果服務器不夠,就用虛擬機當服務器。Docker並不能改變這個狀況,它還不適合作爲一個服務器。


4. 如何寫好docker run指令

以Docker安裝Redis服務爲例。
我們首先需要pull一個Redis鏡像(在不指定特定版本時,默認安裝最新的版本):

docker pull redis

之後可以通過docker image ls查看pull後的鏡像列表。

要想使用鏡像,需要用docker run指令。
很多博客只是說要docker run -p 6379:6379 --name redis redis就可以運行Redis服務,其中-p是配置端口號。但這樣簡單的一行代碼仍給了我很大困惑:

  1. 不使用Docker鏡像時,我們需要編寫配置文件redis.conf、再用redis-server redis.conf運行Redis-server。這裏如果想修改配置,該如何指定配置文件?
  2. 用上述方法開啓了Redis後,這個redis指的是redis-server嗎?最後的兩個redis分別是什麼意思?

反覆試驗後我得到了一個自己最心儀的docker run指令:

docker run -p 6379:6379 --name redis_server -v /root/doc/redis.conf:/etc/redis/redis.conf -v /root/doc/data:/data -d redis redis-server /etc/redis/redis.conf --appendonly yes

  • -p是指定端口,形式爲:主機端口/容器端口。如果這裏寫成6378:6379,說簡單點就是我們在自己的服務器的6378端口可以看到docker容器中6379端口發出的內容。如果我們需要創三個redis服務,分別使用6377:63796378:63796379:6379執行三次docker run就可以分別在自己服務器的三個6377~6379三個端口部署三個Redis服務了。
  • --name redis_server是對要創建的容器進行命名。這裏的意思是用redis鏡像創建一個名爲redis_server的容器。選擇的鏡像redis在命令中寫在了-d後面。
  • -v是指定配置文件位置。Redis有兩個常用的配置:一個是配置文件redis.conf,另一個data文件夾。這裏和-p一樣,也是指定本機文件位置/容器文件位置。如:-v /root/doc/redis.conf:/etc/redis/redis.conf就是在把自己主機/root/doc/redis.conf文件映射到docker容器中的/etc/redis/redis.conf中。我們由此可以先在主機中寫好配置文件,然後就可以使用這個配置文件來啓動Redis服務了。
  • -d是指定該容器一直在後臺運行的意思。
  • redis在前面提到了。是指定的鏡像
  • redis-server /etc/redis/redis.conf --appendonly yes是使用鏡像的指令,這些都是Redis自己的事了。因爲我要使用配置文件去運行redis-server,所以我運行的是這行代碼。如果不需要使用配置文件運行redis-server,直接使用redis,或redis-server即可。然後我指定了一個Redis運行指令:appendonly,是讓Redis中的數據持久化存儲,即將數據保存到磁盤上。

5. 何爲docker exec

在創建好鏡像後,可以使用docker exec -it [鏡像名] bash進入鏡像的bash命令行中。
這也是之前在第2步分鐘提到過的,每個鏡像其實都存在於一個linux系統中。
還是以Redis服務爲例,Redis在開啓redis-server後,往往需要使用redis-cli客戶端。這時,我們就可以先運行docker exec -it redis_server bash進入bash命令行,然後運行redis-cli進入客戶端。

很多時候run一個容器的目的就是進入該容器的bash,常常可以通過sh -c '[command]'合併成一步進行操作:
例如我們希望快速進入一個redis-cli的bash(基於上述已建立好的一個redis_server容器):

$ docker run -it --rm --link some-redis:redis_server redis sh -c 'exec redis-cli -h "$REDIS_PORT_6379_TCP_ADDR" -p "$REDIS_PORT_6379_TCP_PORT"'

注1:docker run --link可以用來鏈接2個容器,使得源容器(被鏈接的容器)和接收容器(主動去鏈接的容器)之間可以互相通信,並且接收容器可以獲取源容器的一些數據,如源容器的環境變量。
注2:docker run --rm是容器運行完成後即刪除。


6. 如何刪除容器

這裏要注意的是:刪除容器之前必須先停止容器。
使用docker ps可以查看到運行中的容器。這裏的容器都是不可以刪除的。
使用docker ps -a查看所有容器。只有停止運行的容器可以刪除。
讓容器停止的指令是docker stop [container_name / container_id]
停止後可以刪除:docker rm [container_name / container_id]

容器的id往往很長,一般輸入前兩個字符即可。


7. 如何編寫Dockerfile

待補

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章