原文地址:http://accjiyun.cn/wan-zhuan-dockerzhi-chang-yong-ming-ling-pian-san/
首先我們來解決一個小問題,使用docker每次都要用sudo,為了讓非root用戶使用docker,可將當前用戶添加到docker用戶組:
sudo groupadd docker
sudo gpasswd -a ${USER} docker # 當前用戶添加到docker group
然后重新登入下用戶就可以直接使用docker命令了。
一、查看docker信息及幫助
# 查看docker版本
docker version
# 顯示docker系統的信息
docker info
# 所有Docker命令幫助
docker help
二、鏡像操作
# 檢索image
docker search image_name
# 下載image
docker pull image_name
# 列出鏡像列表; -a, --all=false Show all images; --no-trunc=false Don't truncate output; -q, --quiet=false Only show numeric IDs
docker images
# 刪除一個或者多個鏡像; -f, --force=false Force; --no-prune=false Do not delete untagged parents
docker rmi image_name
# 顯示一個鏡像的歷史; --no-trunc=false Don't truncate output; -q, --quiet=false Only show numeric IDs
docker history image_name
# 保存鏡像到一個tar包; -o, --output="" Write to an file
docker save image_name -o file_path
# 加載一個tar包格式的鏡像; -i, --input="" Read from a tar archive file
docker load -i file_path
# 機器a
docker save image_name > /home/save.tar
# 使用scp將save.tar拷到機器b上,然后:
docker load < /home/save.tar
三、容器操作
1.啟動容器
# 在容器中運行"echo"命令,輸出"hello word"
docker run image_name echo "hello word"
# 交互式進入容器中
docker run -i -t image_name /bin/bash
# 在容器中安裝新的程序
docker run image_name apt-get install -y app_name
# 運行一個新容器,同時為它命名、端口映射、文件夾映射。以redmine鏡像為例
docker run --name redmine -p 9003:80 -p 9023:22 -d -v /var/redmine/files:/redmine/files -v /var/redmine/mysql:/var/lib/mysql sameersbn/redmine
# 一個容器連接到另一個容器
docker run -i -t --name sonar -d -link mmysql:db tpires/sonar-server
sonar
-d:以守護進程方式運行(后台),並返回容器ID;
-P:默認匹配docker容器的5000端口號到宿主機的49153 to 65535端口
-p <HOT_PORT>:<CONTAINER_PORT>:指定端口號
--name: 指定容器的名稱
--rm:退出時刪除容器
-a stdin 指定標准輸入輸出內容類型,可選 STDIN/STDOUT / STDERR 三項;
-i 以交互模式運行容器,通常與 -t 同時使用;
-t 為容器重新分配一個偽輸入終端,通常與 -i 同時使用;
--dns 8.8.8.8 指定容器使用的DNS服務器,默認和宿主一致;
--dns-search example.com 指定容器DNS搜索域名,默認和宿主一致;
-h "mars" 指定容器的hostname;
-e username="ritchie" 設置環境變量;
--env-file=[] 從指定文件讀入環境變量;
--cpuset="0-2" or --cpuset="0,1,2"
綁定容器到指定CPU運行;
2.查看容器
# 列出當前所有正在運行的container
docker ps
# 列出所有的container
docker ps -a
# 列出最近一次啟動的container
docker ps -l
3.修改容器
# 保存對容器的修改; -a, --author="" Author; -m, --message="" Commit message
docker commit ID new_image_name
4.容器其它基本操作
# 刪除所有容器
docker rm `docker ps -a -q`
# 刪除單個容器; -f, --force=false; -l, --link=false Remove the specified link and not the underlying container; -v, --volumes=false Remove the volumes associated to the container
docker rm Name/ID
# 停止、啟動、殺死一個容器
docker stop Name/ID
docker start Name/ID
docker kill Name/ID
# 從一個容器中取日志; -f, --follow=false Follow log output; -t, --timestamps=false Show timestamps
docker logs Name/ID
# 列出一個容器里面被改變的文件或者目錄,list列表會顯示出三種事件,A 增加的,D 刪除的,C 被改變的
docker diff Name/ID
# 顯示一個運行的容器里面的進程信息
docker top Name/ID
# 從容器里面拷貝文件/目錄到本地一個路徑
docker cp Name:/container_path to_path
docker cp ID:/container_path to_path
# 重啟一個正在運行的容器; -t, --time=10 Number of seconds to try to stop for before killing the container, Default=10
docker restart Name/ID
# 附加到一個運行的容器上面; --no-stdin=false Do not attach stdin; --sig-proxy=true Proxify all received signal to the process
docker attach ID
四、鏡像倉庫操作
# 登陸registry server; -e, --email="" Email; -p, --password="" Password; -u, --username="" Username
docker login
# 發布docker鏡像
docker push new_image_name
五、網絡管理
docker run -P:隨機分配端口號
docker run -p 5000:5000:綁定特定端口號(主機的所有網絡接口的5000端口均綁定容器的5000端口)
docker run -p 127.0.0.1:5000:5000:綁定主機的特定接口的端口號
docker run -d -p 127.0.0.1:5000:5000/udp training/webapp python app.py:綁定udp端口號
docker port <CONTAINER_ID> 5000:查看容器的5000端口對應本地機器的IP和端口號
# 使用Docker Linking連接容器:
Docker為源容器和接收容器創建一個安全的通道,容器之間不需要暴露端口,接收的容器可以訪問源容器的數據
docker run -d -P --name <CONTAINER_NAME> --link <CONTAINER_NAME_TO_LINK>:<ALIAS>
六、數據管理
Data Volumes:volume是在一個或多個容器里指定的特殊目錄
- 數據卷可以在容器間共享和重復使用
- 可以直接修改容器卷的數據
- 容器卷里的數據不會被包含到鏡像中
- 容器卷保持到沒有容器再使用它
可以在容器啟動的時候添加-v參數指定容器卷,也可以在Dockerfile里用VOLUMN命令添加
docker run -d -P --name web -v /webapp training/webapp python app.py
也可以將容器卷掛載到宿主機目錄或宿主機的文件上,<容器目錄或文件>的內容會被替換為<宿主機目錄或文件>的內容,默認容器對這個目錄有可讀寫權限
docker run -d -P --name web -v <宿主機目錄>:<容器目錄> training/webapp python app.py
可以通過指定ro,將權限改為只讀
docker run -d -P --name web -v <宿主機目錄>:<容器目錄>:ro training/webapp python app.py
在一個容器創建容器卷后,其他容器便可以通過--volumes-from共享這個容器卷數據,如下:
docker run -d -v /dbdata --name db1 training/postgres echo Data-only container for postgres
首先啟動了一個容器,並為這個容器增加一個數據卷/dbdata,然后啟動另一個容器,共享這個數據卷
docker run -d --volumes-from db1 --name db2 training/postgres
此時db2使用了db1的容器卷,當容器db1被刪除時,容器卷也不會被刪除,只有所有容器不再使用此容器卷時,才會被刪除
docker rm -v:刪除容器卷
除了共享數據外,容器卷另一個作用是用來備份、恢復和遷移數據
docker run --volumes-from db1 -v /home/backup:/backup ubuntu tar cvf /backup/backup.tar /dbdata
啟動一個容器數據卷使用db1容器的數據卷,同時新建立一個數據卷指向宿主機目錄/home/backup,將/dbdata目錄的數據壓縮為/backup/backup.tar
docker run -v /dbdata --name dbdata2 ubuntu /bin/bash
docker run --volumes-from dbdata2 -v /home/backup:/backup busybox tar xvf /backup/backup.tar
啟動一個容器,同時把backup.tar的內容解壓到容器的backup
七、使用 Dockerfile 創建鏡像
使用命令行的方式創建 Docker 鏡像通常難以自動化操作。在更多的時候,我們使用 Dockerfile 來創建 Docker 鏡像。Dockerfile 是一個純文本文件,它記載了從一個鏡像創建另一個新鏡像的步驟。撰寫好 Dockerfile 文件之后,我們就可以輕而易舉的使用 docker build
命令來創建鏡像了。
Dockerfile 非常簡單,僅有以下命令在 Dockerfile 中常被使用:
命令 | 參數 | 說明 |
---|---|---|
# | - | 注釋說明 |
FROM | <image>[:<tag>] | 從一個已有鏡像創建,例如ubuntu:latest |
MAINTAINER | Author <some-one@example.com> | 鏡像作者名字,如Max Liu <some-one@example.com> |
RUN | <cmd>或者['cmd1', 'cmd2'⋯] | 在鏡像創建用的臨時容器里執行單行命令 |
ADD | <src> <dest> | 將本地的<src>添加到鏡像容器中的<dest>位置 |
VOLUME | <path>或者['/var', 'home'] | 將指定的路徑掛載為數據卷 |
EXPOSE | <port> [<port>...] | 將指定的端口暴露給主機 |
ENV | <key> <value> 或者 <key> = <value> | 指定環境變量值 |
CMD | ["executable","param1","param2"] | 容器啟動時默認執行的命令。注意一個Dockerfile中只有最后一個CMD生效。 |
ENTRYPOINT | ["executable", "param1", "param2"] | 容器的進入點 |
下面是一個 Dockerfile 的例子:
# This is a comment
FROM ubuntu:14.04
MAINTAINER Kate Smith <ksmith@example.com>
RUN apt-get update && apt-get install -y ruby ruby-dev
RUN gem install sinatra
這里其他命令都比較好理解,唯獨 CMD
和 ENTRYPOINT
我需要特殊說明一下。CMD
命令可用指定 Docker 容器啟動時默認的命令,例如我們上面例子提到的 docker run -it ubuntu:latest sh -c '/bin/bash'
。其中 sh -c '/bin/bash'
就是通過手工指定傳入的 CMD。如果我們不加這個參數,那么容器將會默認使用 CMD 指定的命令啟動。ENTRYPOINT 是什么呢?從字面看是進入點。沒錯,它就是進入點。ENTRYPOINT 用來指定特定的可執行文件、Shell 腳本,並把啟動參數或 CMD 指定的默認值,當作附加參數傳遞給 ENTRYPOINT。
不好理解是吧?我們舉一個例子:
ENTRYPOINT ['/usr/bin/mysql']
CMD ['-h 192.168.100.128', '-p']
假設這個鏡像內已經准備好了 mysql-client,那么通過這個鏡像,不加任何額外參數啟動容器,將會給我們一個 mysql 的控制台,默認連接到192.168.100.128 這個主機。然而我們也可以通過指定參數,來連接別的主機。但是不管無論如何,我們都無法啟動一個除了 mysql 客戶端以外的程序。因為這個容器的 ENTRYPOINT 就限定了我們只能在 mysql 這個客戶端內做事情。這下是不是明白了~
因此,我們在使用 Dockerfile 創建文件的時候,可以創建一個 entrypoint.sh
腳本,作為系統入口。在這個文件里面,我們可以進行一些基礎性的自舉操作,比如檢查環境變量,根據需要初始化數據庫等等。下面兩個文件是我在日常工作的項目中添加的 Dockerfile 和 entrypoint.sh,僅供參考:
-
https://github.com/starlight36/SimpleOA/blob/master/Dockerfile
-
https://github.com/starlight36/SimpleOA/blob/master/docker-entrypoint.sh
在准備好 Dockerfile 之后,我們就可以創建鏡像了:
docker build -t starlight36/simpleoa .
關於 Dockerfile 的更詳細說明,請參考 https://docs.docker.com/reference/builder/。