docker使用總結
安裝注意
- 不要直接用apt-get安裝docker, apt-get安裝的版本有些低。 安裝用curl -sSL https://get.docker.com/ubuntu/ | sudo sh 可以安裝最新版
- docker對linux內核版本有要求,內核版本不能太低, 如果太低會導致docker的一些功能不能使用, 比如docker exec 命令在低版本的linux內核下不能用, 運行linux命令uname -r 可以查看linux內核版本, docker官方文檔說linux內核版本不能低于3.13 , 升級linux內核 : sudo apt-get install linux-image-generic-lts-trusty 手動升級方法:
- 高版本的linux內核不支持aufs的存儲類型,建議用devicemapper存儲類型。 ##封裝原則
- 容器要有專職, 盡量一個容器只有一個服務,原則上說一個進程就一個容器,不要讓一個容器里面有多個進程,進程越大,耦合性越大。
- 容器內可以用supervision管理進程,防止進程異常退出。
- 環境變量作為容器配置項, Dockerfile中可以用 ENV設置環境變量 , docker run 命令可以用 -e 設置環境變量。 注意這里設置的環境命令都是root用戶的。 如果想讓Apache 用戶也使用這些環境變量, 執行下面shell命令 env | grep JD_ | sed "s/^/export /g" >> /etc/apache2/envvars 表示以JD_ 開頭的環境變量都設置為Apache的環境變量。 如果是一個純前端的網站項目,你可以獲得環境變量, 可以在index.html 中 加載一個php文件: 在json.php 中獲得環境變量輸出。 ##docker的坑
- 最坑的 --link 鏈接容器。 用docker自帶的--link把多個容器鏈接在以前, 有重啟或升級的問題, 比如很多容器都依賴于 db 這個容器, 然后db容器重啟了, 重啟時docker分配的ip會變, 導致其他依賴于db的容器都要重啟。--link 鏈接的容器還有啟動順序的問題, 需要先啟動db容器再啟動其他依賴于db的容器, 這樣導致 --link和--restart=always 不能一起用, 如果一起用會發現宿主機重啟了, docker容器并沒有全部重啟,因為這時候docker容器是同時被啟動的,并不知道啟動順序。 最后決定不用 --link 鏈接容器了。 另外有兩種鏈接容器的方法,一種是給容器設置固定ip , 這個方法比較復雜: 另外還有一種簡單的鏈接方式, 可以用宿主機的端口鏈接, 比如一個mysql容器,先設置宿主機的3306端口映射到mysql容器中。 然后查宿主機的內網ip , 用ifconfig 查,eth0的網卡可以看見內網ip, 假設內網ip為10.128.130.175 , docker容器是可以訪問這個宿主機內網ip的, 這樣其他容器要鏈接mysql容器,鏈接數據庫時 鏈接 10.128.130.175:3306 即可。 我們可以在docker run啟動容器時用 --add-host 參數為容器設置一個hosts 。這樣容器內代碼可以用指定的域名去訪問數據庫, 不用關心內網ip的變化。
- pid的問題。
docker 容器中的進程有時會生成pid文件, 比如Apache進程會生成的pid文件為 /var/run/apache2/apache2.pid , 當進程啟動時,這個pid文件就存在,當進程退出時,這個pid文件也會被刪除, 我們把正在運行的容器用docker commit 提交為鏡像時會把pid文件也提交到鏡像中,這樣從新鏡像運行容器時,容器可能因為已經存在pid文件而無法啟動。 以Apache為例,可能就會報 “httpd(pid 1) ready runing” 之類的錯誤 , 報錯告訴你httpd正在運行,但其實并沒有運行只是存在pid文件而已。 所以最好是用docker stop 把容器停掉, 再用docker commit 創建鏡像。
pid 的問題還可能會出現在docker run時設置--restart=always 參數的時候, 設置了此參數容器退出了會自動重啟, 宿主機重啟了容器也能自動重啟。 但是容器在重啟的時候很容易pid文件存在。pid文件存在時進程會自動退出, 但又因為設置了--restart=always 進程退出的那一瞬間 容器又自動重啟, 所以容器就在那里不斷的退出再自動重啟退出再自動重啟。 此時 運行命令 docker ps 是能看見容器是運行中的狀態。 但是用 docker exec -it container_name bash 始終進不了容器, 會報如下錯誤:
Cannot run exec command 0eb8e17609dd78c9137c62d94cfaa62795de161d643fc3cb00387b60f11090be in container 8837b983fe2f08f5f3b9999259d5f255a83774b19282b6f9c21a9d688f7f7f2a: No active container exists with ID 8837b983fe2f08f5f3b9999259d5f255a83774b19282b6f9c21a9d688f7f7f2a
No active container exists with ID 這句的意思是說 找不到有效的容器。 但是docker ps又看見容器是在運行中, 為什么會找不到有效的容器? 這是因為這個容器現在其實一直在不斷重啟中, 所以進不去。
解決方法, 可以在容器啟動命令腳本(如 /run.sh) 中 加上一句刪除pid文件的代碼, 如 rm /var/run/apache2/apache2.pid 這樣在啟動進程之前強制刪除了pid文件,就不會重復重啟了。 - docker容器的hosts文件。
在正在運行的容器 用docker exec 進入修改 /etc/hosts 文件 ,這個容器被重啟后會發現 hosts文件會被還原。 所以不要直接修改hosts文件, 需要增加hosts ,在docker run時 用 --add-host 參數。 - 虛擬目錄不會提交到鏡像
Dockerfile 中 VOLUME 指定的目錄 或 docker run 時 -v 參數指定的目錄, 在docker commit 時不會提交到鏡像中。 如果-v 參數指定的容器內的目錄原本有文件, 原本的文件都會被刪除, 只存在宿主機目錄的文件。 - docker容器的重啟。
容器一個容器運行中apache 我們要重啟Apache , 應該怎么重啟? 可能新手會 docker exec -it container_name bash 進入容器, 然后運行 service apache2 restart 啟動Apache , 這樣是不能啟動apache的, 只會把容器停止掉。 因為容器的主進程就是Apache , 主進程退出時會退出容器, 在重啟apache的時候 主進程先退出了, 這時候docker容器也跟著退出了,所以Apache不會重啟。 要重啟Apache 用docker命令: docker restart container_name - 退出容器的方法
如果是docker run 運行一個容器, 沒有加 -d 參數讓它后臺運行, 這時候 ctrl+c 退出進程也會讓容器停止, 如果先退出但不停止容器可以ctrl+p 然后 ctrl+q
</ul>
- 將Ubuntu的源設置為國內的源,這樣安裝軟件會快很多 RUN sed -i "s/archive\.ubuntu\.com/mirrors\.163\.com/g" /etc/apt/sources.list
- RUN
Dockerfile 中可以RUN執行系統命令創建鏡像。不能用RUN命令來常駐進程。 比如不能運行 RUN gearmand -d 。 - ONBUILD
ONBUILD修飾的命令在子Dockerfile文件中也會被執行,舉例說明:
一個Dockerfile中有ONBUILD命令, 如 ONBUILD ADD . /app/src , 運行 docker build -t Image_name . 創建一個名為Image_name的鏡像。 另外在創建一個Dockerfile , 第一個行是 FROM Image_name 現在這個Dockerfile是繼承于前一個Dockerfile的,現在這個Dockerfile在build時會執行他父Dockerfile的 ONBUILD命令, 所以現在這個Dockerfile在build時也會執行 ADD . /app/src 這個命令。 - ENTRYPOINT
感覺 ENTRYPOINT 會比 CMD 更省資源, ENTRYPOINT 使用時用數組形式。如:
entrypoint ["/init.sh", "/usr/bin/supervisord", "-n", "-c", "/etc/supervisord.conf"]
/init.sh 是一個初始化腳本,初始化腳本內容大概為:
```
!/bin/bash
set -e
執行一些初始化代碼
exec “$@”
```
最后要跟上exec “$@” ,這樣才能讓init.sh 腳本后的 supervisord被執行。 - .dockerignore
.dockerignore文件中列的文件不會被 ADD或COPY 指令添加到容器中。
</ul>
- jwilder/nginx-proxy 這是一個nginx反向代理。
啟動nginx反向代理:
docker run --name nginx -d -p 80:80 -v /var/run/docker.sock:/tmp/docker.sock -t --restart=always jwilder/nginx-proxy
再啟動其他容器, 如:
docker run -e VIRTUAL_HOST=yourdomain.com -d tutum/apache-php
nginx的容器會監聽其他容器的啟動, 并根據VIRTUAL_HOST設置域名。這樣可以通過 yourdomain.com 訪問剛才啟動的容器中的網站了。 - tutum/apache-php 這個鏡像是一個好用的apache環境。 </ul>
Dockerfile編寫技巧
好用的docker鏡像
清理docker
docker info 可以查看docker的信息, /var/lib/docker/devicemapper/devicemapper 目錄下存放了docker的文件, 可以用du -h --max-depth=1 看文件的大小。
刪除為none的鏡像,可以立馬回收空間:
docker images --no-trunc| grep none | awk '{print $3}' | xargs -r docker rmi
刪除退出了的容器:
docker rm `docker ps -a | grep Exited | awk '{print $1 }’
刪除沒有用的鏡像。 (有容器運行的鏡像不會被刪除):
docker rmi `docker images -aq`
本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!