Docker 基本用法
1. 安裝社區版docker-ce 及 nvidia-docker2 插件
通過官網介紹的軟件源的方式安裝. 如果要安裝nvidia-docker,由於其需要與docker-ce的版本匹配,所以如果是手動下載安裝的話需要注意版本號.
nvidia-docker對宿主機的要求是安裝了nvidia驅動程序和docker程序,而CUDA toolkit安裝在容器里邊,而不必安裝在宿主機上. 因此包含cuda toolkit的鏡像通常都很大.
安裝之后重載Docker daemon: sudo pkill -SIGHUP dockerd
運行示例: docker run --runtime=nvidia --rm nvidia/cuda nvidia-smi
離線安裝: ubuntu下借助apt-rdepends找出所有的遞歸依賴: apt-get download $(apt-rdepends docker-ce|grep -v "^ ")
CentOS等其它版本的安裝參考: https://github.com/gzvincen/docker-offline-install-package
nvidia深度學習開發棧如下圖所示:
2. 鏡像加速
對於使用 upstart 的系統而言,編輯 /etc/default/docker 文件,在其中的 DOCKER_OPTS 中配置加速器地址:
DOCKER_OPTS="--registry-mirror=https://registry.docker-cn.com"
或者daocloud的http://4ce12ab7.m.daocloud.io
重新啟動服務:
sudo service docker restart
3. 建立 docker 用戶組
默認情況下,docker 命令會使用 Unix socket 與 Docker 引擎通訊。而只有 root 用戶和 docker 組的用戶才可以訪問 Docker 引擎的 Unix socket。出於安全考慮,一般 Linux 系統上不會直接使用 root 用戶。因此,更好地做法是將需要使用 docker 的用戶加入 docker 用戶組。
建立 docker 組:
sudo groupadd docker
將當前用戶加入 docker 組:
sudo usermod -aG docker $USER
退出當前終端並重新登錄才可生效(如果急用,運行docker時加sudo)。
4. 運行容器
docker run -dit ubuntu
加--rm參數,在容器終止運行后自動刪除容器文件。
5. 進入容器命令行
docker attach 243c
# 如果鏡像的入口並非shell,則不能夠進入shell,需要執行 docker exec
docker exec -it 69d1 bash
6. 容器與宿主機互相拷貝文件: docker cp
Usage: docker cp [OPTIONS] CONTAINER:SRC_PATH DEST_PATH|-
docker cp [OPTIONS] SRC_PATH|- CONTAINER:DEST_PATH
7. 將容器保存為鏡像:
docker commit 容器id 鏡像名稱
8. 上傳鏡像到倉庫:
打tag: docker tag 鏡像名稱 遠程鏡像名稱tag
docker image ls
進行查看
上傳docker push 遠程鏡像名稱tag
為了加速, 可以使用HTTPS_PROXY=https://xxx docker push
9. 停止容器: docker stop --time=20 container_name
會發送信號SIGTERM並等待一定時間后終止.
docker kill
發出SIGKILL 強制終止
10. 刪除已停止的容器: 較新版的刪除所有已停止的容器快捷方式: docker container prune
查出容器的 ID: docker container ls --all
刪除指定的容器文件 docker container rm [containerID]
刪除鏡像 docker rmi -f [image ID]
如果有對應的啟動的容器需要-f
(force)一並刪除
11. 列出容器: 正在運行中的程序: docker ps
, 使用-a
包括已停止的容器.
12. 鏡像無法聯網, 可嘗試在docker run時加 --net host
13. 啟動已經終止的容器: docker start 容器id
14. detach 即退出容器shell而不終止容器: Ctrl+p + Ctrl+q
15. 容器導出/導入到文件
docker export -o project-image.tar 45589e5912ce
導入容器鏡像用import : docker import my_ubuntu_v3.tar runoob/ubuntu:v4
可以將導入的鏡像命名為后者, 如果不命名,則是<none>
. 另外,還可以用save命令將鏡像完整保存,包括歷史版本和元數據信息,所以文件可能比較大。相應的用load命令導入: docker load < project-image.tar
導入之后通過docker images
命令可以看到新導入的鏡像.
區別是export導出的是容器, save導出的是鏡像, 另外,最好用save導出比較完整,否則容易出現cuda與驅動不匹配的問題.
另外,導出到文件時進行壓縮可節省空間:
導出鏡像: docker save ubuntu:v4 | gzip -c > ubuntu-v4.tgz
導入鏡像: gunzip -c project-v2.tgz | docker load
16. 移除所有的容器和鏡像(大掃除):
docker kill $(docker ps -q) ; docker rm $(docker ps -a -q) ; docker rmi $(docker images -q -a)
17. 驗證GPU可用性: docker run --runtime=nvidia --rm nvidia/cuda nvidia-smi
--rm 表示運行完畢就刪除容器, -dit -d表示以daemon后台運行, -i交互式-t新的偽終端.
如果不加-it運行的時候無法接受ctrl+c等輸入.
容器的啟動方式: nvidia-docker start 071b0b
Docker 更多介紹
關於網絡配置
在使用默認的橋接模式下,容器啟動后會被分配一個與docker0在同一網段的地址,在容器內部默認顯示為eth0,在宿主機上產生一個臨時的vethXXX接口。
端口映射
在主機上查看端口映射的方式為docker ps(橋接方式會顯示端口)、docker inspect [id]、netstat -nlp
netstat可能只會顯示出tcp6的監聽狀態,實際上ipv4的地址也監聽了。
在訪問容器內的服務時,如將mysql的3306端口映射到主機上的13306端口,則通過13306端口通信時客戶端使用的是docker0的地址,需要配置mysql容許建立連接的ip地址。除了設置bind-address外,可能還需要設置特定用戶的權限:
update user set host='%或者ip' where xxx;
flush privileges;
可以通過命令
telnet localhost 13306
來檢測是否能夠建立tcp連接
容器連接
由於容器間應用程序被相互隔離,在不使用--link連接容器時難以從一個容器內建立到另外一個容器內的進程的連接,除非使用共享的socket文件來實現unix socket通信(掛載相同的卷或者同樣具有對某一系統目錄的寫權限)。在知道容器的ip時可以發送ping ICMP數據包
要建立容器之間的鏈接,必須在啟動時通過參數--name $container_name給容器命名
--link name:alias Docker在兩個容器之間創建了一個安全的隧道,這是鏈接的巨大優勢, 通過連接,我們不需要向外部網絡暴露端口.
在連接了目標容器后,我們可以在源容器中查看到/etc/hosts文件中多了一個目標容器的host解析:
172.17.0.2 alias 13065893a1dd name
執行netstat -nlt不能夠看到目標容器中開放的端口,但是可以訪問。
容器的hostname
在用docker運行一個鏡像時如果使用橋接方式,沒有用-h指定hostname,則使用產生的容器id的一部分作為hostname,解析為容器內eth0的地址。如果需要連接兩個容器,最好是指定hostname而不是ip的形式來建立tcp連接。
如果通過--net='host'指定容器使用host的網絡配置,那么hostname、網絡接口、dns等信息完全一樣。
容器內的網絡配置是只讀的,如果想要在容器內修改配置,需要在運行時加上參數--cap-add=NET_ADMIN來賦予修改權限(如果采用了host方式會影響到host主機的網絡配置)。
數據存儲
容器停止后再次運行時(docker start)上次修改后的數據得以保留,不會丟失。而從鏡像重新創建一個容器運行時是鏡像原本的數據。
將數據從容器中拷出來:
docker cp containerId:/file/path/within/container /host/path/target
更方便的方式可能就是使用-v掛載外部卷了,直接在容器外部的文件中讀寫。