Docker指南
介绍
Docker 是一个能够把开发的应用程序自动部署到容器的开源引擎,是一个轻量级容器管理引擎,它改变了传统软件的交付和运行方式。
Image
镜像类似于虚拟机镜像,可以理解为面向 Docker 引擎的只读模板,是由文件系统叠加而成。镜像是 Docker 运行容器的前提,用户基于镜像来运行容器。
镜像是分层的,AUFS(Advanced Union File System),Dockerfile 中每运行一条 RUN 指令,镜像添加新的一层。
镜像名
- 仓库名/镜像名:标签
- 如果没有指定任何标签,则自动为镜像设置一个latest标签
dangling镜像
dangling 镜像就是 docker images 命令中出现的,REPOSITORY 和 TAG 都显示为 <none>
的镜像
Container
容器类似于一个轻量级的沙箱,Docker 利用容器来运行和隔离应用,容器是镜像的一个运行实例。
Repository
仓库类似于代码仓库,是 Docker 集中存放镜像文件的地方
每个仓库集中存放一组关联镜像的集合,通过不同的 TAG 来区分,TAG 用来标记来自同一个仓库的不同镜像
Registry
注册服务器存放不同的仓库。 一个 Docker Registry 中可以包含多个 仓库(Repository
);每个仓库可以包含多个 标签(Tag
);每个标签对应一个镜像。
安装
更新apt包索引
1
sudo apt-get update
安装必要工具包
1 2 3 4 5 6 7
sudo apt-get install \ apt-transport-https \ ca-certificates \ curl \ gnupg-agent \ software-properties-common \ lsb-release
添加Docker GPG秘钥
为了确认所下载软件包的合法性,需要添加软件源的
GPG
密钥1 2 3 4 5
$ curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg # 官方源 # $ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
向sources.list添加Docker软件源
1 2 3 4 5 6 7 8 9
$ echo \ "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://mirrors.aliyun.com/docker-ce/linux/ubuntu \ $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null # 官方源 # $ echo \ # "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \ # $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
更新apt
1
sudo apt-get update
安装Docker
1
sudo apt-get install docker-ce docker-ce-cli containerd.io
启动docker
1 2 3 4 5
# 将docker服务添加到系统启动时的自动运行列表 sudo systemctl enable docker # 立即启动docker服务 sudo systemctl start docker
验证是否安装成功
1
sudo docker run hello-world
建立docker用户组
只有
root
用户和docker
组的用户才有访问Docker引擎的权限建立
docker
组1
sudo groupadd docker
将当前用户加入
docker
组1
sudo usermod -aG docker $USER
无权限运行docker
1
docker run -rm hello-world
如果还是存在权限问题,注意
/var/run/docker.sock
的相关权限1
ls -l /var/run/docker.sock
如果需要,可以将
docker.sock
的所有者改为docker用户组1 2
sudo chown root:docker /var/run/docker.sock sudo chmod 0660 /var/run/docker.sock
镜像操作命令
创建镜像
1
2
3
4
5
# 基于已有的容器创建镜像
docker commit -m "message" -a "author" CONTAINER REPOSITORY:TAG
# 基于本地模板导入
cat XOS.tar | docker import - lqshow/test:v1.0
查看镜像
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 查找所有镜像
docker search image_name
# 列出所有镜像
# docker images 等价于 docker image ls
docker image ls
# 列出部分镜像
docker image ls ubuntu
docker image ls ubuntu:18.04
# 查看在monge:3.2之后创建的镜像
docker image ls --filter since=mongo:3.2
# 列出镜像的ID
docker image ls -q
# 列出镜像结果,只包含镜像ID和仓库名
docker image ls --format ": "
镜像操作
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 获取镜像
# docker pull [选项] [Docker Registry地址[:端口号]/]仓库名[:标签]
#
# docker镜像仓库地址格式一般是 <域名/IP>[:端口号] ,默认地址 Docker Hub(docker.io)
docker pull image_name
# 仓库名是两段式名称,即 <用户名>/<软件名>
# 对于Docker Hub,不给出用户名则默认为library即官方镜像
docker pull docker-reg.basebit.me:5000/basebit/xdp-sdk-jre8
# 运行镜像
docker run -it --rm ubuntu:18.04 bash
# 发布镜像
docker push lqsow/static_web
# 重命名镜像
docker tag image_name new_image_name
# 获取镜像的创建历史
docker history image_name
# 查看镜像
docker inspect nginx:1.13.0-alping -f .ContainerConfig
导入导出镜像
1
2
3
4
5
6
7
# 保存(导出)镜像
docker save -o <image_name>.tar <image_id>
docker save <image_id> > <image_name>.tar
# 加载(导入)镜像
dokcer load --input img_java.tar
docker load < img_java.tar
更新镜像
直接拉取最新镜像
1
docker pull 镜像名:标签
如果拉取后显示
1
Status: Image is up to date for nginx:latest
代表本地镜像已经是最新的
如果提示
1
Status: Downloaded newer image for nginx:latest
就说明本地镜像不是最新的
删除镜像
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# 1. 当有该镜像创建的容器存在时,镜像文件是无法被删除的。正确做法是先删除依赖该镜像的相关容器,然后再删除此镜像。
# 2. 强行使用 -f 参数删除,会带来 none 镜像。
# 删除一个镜像
# 等价于docker image rm
# docker rmi [选项] <镜像1> [<镜像2> ...]
# <镜像>可以是镜像短ID,镜像长ID,镜像名或者镜像摘要
docker rmi image_name
# 删除多个镜像
docker rmi image_name image_name2
# 批量删除临时镜像文件
docker rmi $(docker images -q -f dangling=true)
# 删除所有镜像
docker rmi -f `docker images -a -q`
# 删除none镜像
docker rmi $(docker images | grep "none" | awk '{print $3}')
# 批量删除repository ,tag 为none 的镜像
docker images |grep none|awk '{print $3}'|xargs docker rmi
# 镜像摘要
docker image ls --digests
docker image rm xxx@sha256:xxx
镜像的唯一标识是ID和摘要
一个镜像可以有多个标签
如果删除信息是
Untagged
,则是删除指定标签
Delete
则是删除整个镜像
commit
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 1. 用nginx镜像启动一个容器webserver,后台运行,本地8080端口映射到容器的80端口
docker run --name webserver -d -p 8080:80 nginx
# 2. 修改页面内容
docker exec -it webserver bash
echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html
exit
# 3. 查看具体的改动
docker diff webserver
# 4. 使用commit保存
docker commit \
--author "Jao" \
--message "修改了网页" \
webserver \
nginx:v2
# 5. 查看新镜像
docker image ls nginx
docker history nginx:v2
# 6. 运行新镜像
docker run -d -p 8081:80 --name web2 nginx:v2
容器操作命令
启动容器有两种方式,一种是基于镜像新建一个容器并启动,另外一个是将在终止状态(exited)的容器重新启动。
创建启动容器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# 下面的命令创建一个随机名称容器并且运行Ubuntu
# 然后输出一个 “Hello World”,之后终止容器
# 1. 检查本地是否存在Ubuntu镜像,不存在则链接到 docker hub,自动下载到本地宿机
# 2. 如果不指定一个镜像的版本标签,如下只使用 Ubuntu,Docker 将默认使用 Ubuntu:latest 镜像
# 3. 容器的命名必须是唯一的
docker run ubuntu:18.04 /bin/echo 'Hello world'
# 下面的命令则启动一个 bash 终端,允许用户进行交互
# -t分配一个伪终端并绑定到容器的标准输入上
# -i让容器的标准输入打开
docker run -t -i ubuntu:18.04 /bin/bash
# 指定容器名
docker run -t -i --name test ubuntu:18.04 /bin/bash
# 后端运行并映射80端口
docker run -d -p 80:80 --name app_port basebit/xdp-sdk-jre8
# 设置环境变量
docker run --rm -it --name test \
--env MYHOME=/home \
--env TEST=/home \
--env PATH=$PATH:/home \
centos bash
# 运行多条指令
docker run -d \
--restart always \
-p 13200:13200 \
--volume /root/.m2:/root/.m2 \
--env NODE_ENV=test \
enigma:0.0.1 \
/bin/sh -c 'cd /data/project/service; npm run build-xfs; ./bin/start.sh'
启动参数
options | desc |
---|---|
-i | 保证容器中的 STDIN 是开启的,进行交互式操作 |
-t | 为要创建的容器分配一个伪 tty 终端 |
-d/–detach | 后台运行容器,并返回容器 ID |
–name | 指定容器名称 |
-e/–env | 配置容器内的环境变量 |
–link | 链接到另外一个容器 |
–rm | 当容器退出时自动删除它 |
-v/–volume | 挂载数据卷(映射的卷),可以使用多次,即挂载多个数据卷 |
–restart | 重启策略( unless-stopped|always) |
-p/–publish | 把容器端口映射到主机端口 |
-P | 对外公开在 Dockerfile 中的 EXPOSE 指令中设置的所有端口 |
–hostname | 设置容器host |
加入参数
-d
,此时容器会在后台运行并不会把输出的结果 (STDOUT) 打印到宿主机上面,可以通过docker logs CONTAINERID
或docker container logs CONTAINERID
去查看输出
当利用 docker run
来创建容器时,Docker 在后台运行的标准操作包括:
- 检查本地是否存在指定的镜像,不存在就从 registry 下载
- 利用镜像创建并启动一个容器
- 分配一个文件系统,并在只读的镜像层外面挂载一层可读写层
- 从宿主主机配置的网桥接口中桥接一个虚拟接口到容器中去
- 从地址池配置一个 ip 地址给容器
- 执行用户指定的应用程序
- 执行完毕后容器被终止
启动已终止容器
可以利用 docker container start
命令,直接将一个已经终止(exited
)的容器启动运行。
终止容器
可以使用 docker container stop
来终止一个运行中的容器。
此外,当 Docker 容器中指定的应用终结时,容器也自动终止。
终止状态的容器可以用 docker container ls -a
命令看到。
处于终止状态的容器,可以通过 docker container start
命令来重新启动。
此外,docker container restart
命令会将一个运行态的容器终止,然后再重新启动它。
查看容器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 列出正在运行的容器
docker ps
# 列出全部容器
docker ps -a
# 列出最后一次运行的容器
docker ps -l
# 获取容器元数据
docker inspect CONTAINER
docker inspect --format='' CONTAINER
# 查看容器进程
docker top CONTAINER
# 查容器的端口映射
docker port CONTAINER
容器日志
1
2
3
4
5
6
7
8
9
10
11
# 跟踪日志输出, 效果类似于tail -f
docker logs -f CONTAINER
# 获取日志最后10行
docker logs --tail 10 CONTAINER
# 获取最新日志
docker logs -ft --tail 0 CONTAINER
# 匹配日志
docker logs CONTAINER 2>&1| grep "ERROR"
容器操作
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 从容器里拷贝文件到本地
docker cp a136a050da25:/home/file.txt ./
# 从本地拷贝文件到容器里
docker cp Dockerfile xdp-workspace-api:/data/project/service/logs/workspace/
# 容器重名
docker rename CONTAINER NEW_NAME
# 停止、启动、杀死、重启一个容器
docker stop CONTAINER
docker start CONTAINER
docker kill CONTAINER
docker restart CONTAINER
附加进入容器
需要进入容器进行操作时,推荐使用
docker exec
命令
附加到一个运行的容器上面(前提是此Container已经运行中)
命令输完后,需按下回车才能进入该会话 退出容器(不关闭容器):
Ctrl+P+Q
退出容器(关闭):exit
1
2
3
4
5
6
7
8
9
$ docker run -dit ubuntu
243c32535da7d142fb0e6df616a3c3ada0b8ab417937c853a9e1c251f499f550
$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
243c32535da7 ubuntu:latest "/bin/bash" 18 seconds ago Up 17 seconds nostalgic_hypatia
$ docker attach 243c
root@243c32535da7:/#
如果从这个 stdin 中 exit,会导致容器的停止。
运行交互式的容器
docker exec
后边可以跟多个参数
只用 -i
参数时,由于没有分配伪终端,界面没有我们熟悉的 Linux 命令提示符,但命令执行结果仍然可以返回。
当 -i
-t
参数一起使用时,则可以看到我们熟悉的 Linux 命令提示符。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$ docker run -dit ubuntu
69d137adef7a8a689cbcb059e94da5489d3cddd240ff675c640c8d96e84fe1f6
$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
69d137adef7a ubuntu:latest "/bin/bash" 18 seconds ago Up 17 seconds zealous_swirles
$ docker exec -i 69d1 bash
ls
bin
boot
dev
...
$ docker exec -it 69d1 bash
root@69d137adef7a:/#
此外,exec
还有以下用法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 在容器中打开交互式任务
docker exec -it a136a050da25 /bin/bash
# 以 root 权限进入容器
docker exec -it -u root docker-jenkins /bin/bash
# 在容器内创建空文件
docker exec -d a136a050da25 touch /home/new_file
# 查看环境变量
docker exec -it 7984cfc7d174 env
# 查看host文件
docker exec -it 7984cfc7d174 cat /etc/hosts
如果从这个 stdin 中 exit,不会导致容器的停止。所以推荐使用
docker exec
导入导出
导出容器快照到本地镜像 导出一个已经创建的容器到一个文件
1 2 3 4
$ docker container ls -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 7691a814370e ubuntu:18.04 "/bin/bash" 36 hours ago Exited (0) 21 hours ago test $ docker export 7691a814370e > ubuntu.tar
导入容器快照为镜像 导出的文件可以使用
docker import
命令导入成为镜像 通过该方式导入,仅保存容器当前的快照状态,需要重新指定标签等元数据信息1 2 3 4 5
# 本地容器 $ cat ubuntu.tar | docker import - test/ubuntu:v1.0 $ docker image ls REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE test/ubuntu v1.0 9d37a6082e97 About a minute ago 171.3 MB
此外,也可以通过指定 URL 或者某个目录来导入,例如
1
$ docker import http://example.com/exampleimage.tgz example/imagerepo
删除容器
运行中的容器是不可以删除的,必须先stop或kill
如果要删除一个运行中的容器,可以添加
-f
参数。Docker 会发送SIGKILL
信号给容器。
1
2
3
4
5
6
7
8
9
10
11
12
# 删除单个容器
docker stop CONTAINER && docker rm CONTAINER
# 删除所有容器
docker rm 'docker ps -a -q'
# 删除所有退出的容器
docker stop $(docker ps -a | grep "Exited" | awk '{print $1 }')
docker rm $(docker ps -a | grep "Exited" | awk '{print $1 }')
# 清理掉所有处于终止状态的容器
$ docker container prune
查看使用情况
1
2
3
4
5
# 查看占用分布
docker system df
# 查看空间占用细节
docker system df -v
清理空间
1
2
3
4
5
6
7
8
9
10
11
# 清除所有未被使用的镜像和悬空镜像
docker system prune -a
# 强制删除
docker system prune -f
# 删除悬空的镜像
docker image prune
# 删除无用的容器
docker container prune
悬空镜像指的是没有被任何标签(tag)引用的镜像
查看节点容器运行情况
1
docker stats --no-stream --format "table \t\t\t" | sort -k 4 -h