镜像操作
相关概念
- 仓库: 存放镜像文件的场所,仓库包含如下两种
- DOcker仓库: 每个仓库集中存放某一类镜像, 这些镜像通过不同的标签区分; 例如存放Ubuntu镜像的仓库,其中包含了16.04, 18.04等多个版本
- 仓库注册服务器: 存放仓库的地方, 里面往往包含了多个仓库
- 镜像: 镜像类似与虚拟机镜像, 可以理解为一个只读模板
- 容器: 容器类似一个轻量级的沙箱, Docker用来运行和隔离应用, 容器是从镜像创建的应用运行实例
镜像拉取
- Docker镜像是运行容器的基础,如果运行容器时镜像不存在,Docker会尝试去Docker Hub公共注册服务器中的仓库中下载
- 拉取命令格式
docker [image] pull NAME[:TAG]
- image是本地的镜像名,用于区分镜像; NAME是镜像仓库名,TAG用来区分版本; 如果不指定TAG,默认拉去最近的镜像
- 例如:
docker pull ubuntu:18.04
- 对于ubuntu镜像, 可能有多种不同的ubuntu镜像仓库, 所以拉取时,严格来说还需要指定仓库地址(Registry, 注册服务器), 默认使用官方Docker Hub服务; 例如
docker pull hub.c.163.com/public/ubuntu:18.04
- 下载镜像过程中, 镜像文件一般由若干层(layer)组成, e9afc4f90ab0是层的唯一id,下载时会输出各层信息; 当不同的镜像包含相同的层时,本地仅存储了层的一份内容,减少存储空间
mystack@mystack-pc:~$ sudo docker pull tomcat
Using default tag: latest
latest: Pulling from library/tomcat
e9afc4f90ab0: Pull complete
989e6b19a265: Pull complete
af14b6c2f878: Pull complete
5573c4b30949: Pull complete
fb1a405f128d: Pull complete
612a9f566fdc: Pull complete
cf63ebed1142: Pull complete
fbb20561cd50: Pull complete
76c915a2cfb7: Pull complete
a2c2864c3363: Pull complete
Digest: sha256:11f247df062558074169fb92a54033ab2eb6563bda9765b3a9e53106db3c2f4a
Status: Downloaded newer image for tomcat:latest
docker.io/library/tomcat:latest
镜像查看
images / image ls
- 查看本机下载的镜像
- REPOSITORY: 镜像来自哪个仓库(例如tomcat仓库, 里面包含各种tag的tomcat)
- TAG: 镜像标签
- IMAGE ID: 镜像ID, 如果ID相同, 说明它们指向同一个镜像, 只是具有不同ID
- CREATED: 最后更新时间
- SIZE: 镜像大小, 镜像大小只是表示该镜像逻辑大小, 实际由于相同的镜像层本地只会存一份, 物理占用的存储空间会小于各个镜像大小之和
mystack@mystack-pc:~$ sudo docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
tomcat latest 6055d4d564e1 4 days ago 647MB
mysql latest 9b51d9275906 4 months ago 547MB
tag
- 添加镜像标签
docker tag IMAGE:TAG NEW_IMAGE:NEW_TAG
- 通过tag可以添加一个本地镜像, 可以看到它们的ID相同,指向同一个镜像文件,只是别名不同而已
mystack@mystack-pc:~$ sudo docker tag tomcat:latest mytomcat:1.0
mystack@mystack-pc:~$ sudo docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
mytomcat 1.0 6055d4d564e1 4 days ago 647MB
tomcat latest 6055d4d564e1 4 days ago 647MB
mysql latest 9b51d9275906 4 months ago 547MB
inspect
- 获取镜像的详细信息, 包括制作者, 适应架构, 各层数字摘要等
docker [image] inspect NAME:TAG
mystack@mystack-pc:~$ sudo docker inspect tomcat
[
{
"Id": "sha256:6055d4d564e1d3a508e4781f2261f3620b3c43145d2286955060b6c4343a64bf",
"RepoTags": [
"mytomcat:1.0",
"tomcat:latest"
],
"RepoDigests": [
"tomcat@sha256:11f247df062558074169fb92a54033ab2eb6563bda9765b3a9e53106db3c2f4a"
],
"Parent": "",
"Comment": "",
...
history
- 查看镜像历史, 镜像文件由多个层组成, 通过该子命令可以获得各层内容
docker history NAME:TAG
- 可以看到过长被截断了, 可以使用
--no-trunc
来输出完整内容mystack@mystack-pc:~$ sudo docker history tomcat
IMAGE CREATED CREATED BY SIZE COMMENT
6055d4d564e1 4 days ago /bin/sh -c #(nop) CMD ["catalina.sh" "run"] 0B
<missing> 4 days ago /bin/sh -c #(nop) EXPOSE 8080 0B
<missing> 4 days ago /bin/sh -c set -e && nativeLines="$(catalin… 0B
<missing> 4 days ago /bin/sh -c set -eux; savedAptMark="$(apt-m… 20MB
搜寻镜像
- search子命令可以用来搜寻Docker Hub中的镜像,
docker search [option] keyword
- 常用选项
- -f, —filters filter: 过滤输出
- —format string: 格式化输出
- —limit int: 限制输出结果
- —no-trunc: 不截断输出
- 输出结果包含镜像名, 描述, 收藏数, 是否官方创建, 是否自动创建等
- 搜索官方提供镜像:
docker search --filters=is-official=true tomcat
- 搜索收藏数超过4:
docker search --filters=stars=4 tomcat
mystack@mystack-pc:~$ sudo docker search tomcat
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
tomcat Apache Tomcat is an open source implementati… 2775 [OK]
tomee Apache TomEE is an all-Apache Java EE certif… 79 [OK]
dordoka/tomcat Ubuntu 14.04, Oracle JDK 8 and Tomcat 8 base… 54 [OK]
bitnami/tomcat Bitnami Tomcat Docker Image 35 [OK]
kubeguide/tomcat-app Tomcat image for Chapter 1 29
删除和清理镜像
- 使用标签删除镜像
docker rmi IMAGE [IMAGE...] / docker image rm
, IMAGE可以是标签或ID- 支持的选项
- -f, -force: 强制删除, 即使有容器依赖它
- -no-prune: 不要清理未带标签的父镜像
- 这里可以看到docker image是一个子命令, 其下还有其他子命令, 例如
docker image pull
docker image rm
docker image inspect
- 如果删除使用tag产生的镜像, 即一个镜像有多个标签, 那么只会删除标签而已
- 一般操作如果不加镜像版本时, 默认是latest, 如果不存在就会报错
- 删除时, 会把镜像的每一层都删除掉 ```shell mystack@mystack-pc:~$ sudo docker rmi mytomcat Error: No such image: mytomcat
mystack@mystack-pc:~$ sudo docker rmi mytomcat:1.0 Untagged: mytomcat:1.0
mystack@mystack-pc:~$ sudo docker image rm tomcat Untagged: tomcat:latest Untagged: tomcat@sha256:11f247df062558074169fb92a54033ab2eb6563bda9765b3a9e53106db3c2f4a Deleted: sha256:6055d4d564e1d3a508e4781f2261f3620b3c43145d2286955060b6c4343a64bf Deleted: sha256:eaddaaaeeb4dfc083e045e780865653f50846e60ead2b9f0d1ea5e84831fc06d Deleted: sha256:328d1c4351076d38cda73e9a3eccd2352211d78b3667d7bea96fe91b32d7468d
- 使用镜像ID删除镜像
- 当使用`docker rmi`命令删除时, 如果后面使用镜像ID, 那么会尝试删除指向镜像的所有标签, 然后再删除镜像文件
- 当有镜像创建的容器存在时, 镜像文件默认是无法删除的, 可以使用-f强制删除, 但是推荐先删除容器, 再删除镜像
- 清理镜像
- 使用Docker一段时间后, 系统可能遗留一些临时的镜像文件, 以及一些没有被使用的镜像, 通过`docker image prune`命令来处理
- 常用选项
- -a, -all: 删除所有无用镜像, 不仅包括临时镜像
- -filter filter: 只删除特定镜像
- -f, -force: 强制删除, 不提醒
<a name="tiqkg"></a>
### 创建镜像
- 基于已有容器创建
- 该方法主要使用`docker [container] commit`命令
- 命令格式为`docker [container] commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]`, 常用选项如下
- -a, --author="": 作者信息
- -c, --change=[]: 提交时执行Dockerfile指令,包括CMD | ENTRYPOINT | ENV | EXPOSE | LABEL | ONBUILD | USER | VOLUME | WORKDIR等
- -m,--message="": 提交消息
- -p,--pause=true: 提交时暂停容器运行
- 当docker容器运行时,可以对容器做一些操作(比如添加文件之类的),这时该容器就已经和原镜像不一样了,可以基于该容器构建一个镜像
- 构建命令:`docker commit -m "added a new file" -a "dongxinchen" 3be8b16e6a59 cdx_tomcat:1.0`
- docker image相关命令
- `docker image ls`
- `docker image rm`
- `docker image prune`
- `docker image inspect`
- `docker image pull`
- 基于本地模板导入
- 用户也可以直接从操作系统模板文件中导入一个镜像,使用`docker [container] import`命令
- 格式:`docker [image] import [OPTIONS] file|URL|-[REPOSITORY[:TAG]]`
- 基于Dockerfile创建
- Dockerfile是一个文本文件,利用给定的指令描述基于某个父镜像创建新镜像的过程
<a name="QdKng"></a>
### 存出和载入镜像
- 存出镜像
- 如果要导出镜像到本地文件,可以使用`docker [image] save`命令,支持`-o,-output string`参数,导出镜像到指定文件
- 例如把镜像cdx_tomcat:1.0镜像为文件my_tomcat.tar,`docker save -o my_tomcat.tar cdx_tomcat:1.0`
- 载入镜像
- 可以使用`docker [image] load`将导出的tar文件再导入到本地镜像库,支持`-i,-input string`参数,从指定文件导入镜像:`docker image load -i my_tomcat.tar` `docker image load > my_tomcat.tar`
- 导入后的镜像标签和版本都是原来的cdx_tomcat:1.0
<a name="PNaWH"></a>
### 上传镜像
- 使用`docker [image] push`命令上传镜像到仓库,默认上传到Docker Hub官方仓库,需要登录,命令格式为`docker [image] push NAME[:TAG] | [REGISTRY_HOST[:REGISTRY_PORT]/]NAME[:TAG]`
- 上传时,可以先给镜像添加新标签,然后再上传
- `docker tag test:latest user/test:latest` `docker push user/test:latest`
<a name="khnQG"></a>
## 容器操作
<a name="aDNIm"></a>
### 创建容器
- 容器是镜像的一个运行实例,镜像是只读文件,而容器带有运行时需要的可写文件层
- 新建容器:使用`docker [container] create`创建一个容器,例如`docker container create -it tomcat`这样创建的容器处于创建状态,并未运行
- 启动容器:使用`docker [container] start`启动一个容器
- 新建并启动容器:使用`docker [container] run`等价于先执行create命令后执行start命令,执行该命令时
- 使用伪终端进行交互:`docker run -it ubuntu:18.04 /bin/bash`
- -t:让Docker分配一个伪终端(pseudo-tty)并绑定到容器的标准输入上
- -i:让容器的标准输入保持打开
- 可以看到,容器里的进程很少,只启动了必要的进程而已,像是一个轻量级的虚拟机
```shell
[root@izuf650sjqtwslsibvattnz ~]# docker exec -it 39d759326c55 /bin/bash
root@39d759326c55:/usr/local/tomcat# ps -aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 1.9 4.2 2535888 80092 pts/0 Ssl+ 10:32 0:02 /usr/local/openjdk-11/bin/java -Djava.util.logging.config.file=/usr/local/tomcat/conf/logging.properties -Djava.util.logging.manager=org.apache.
root 45 0.6 0.1 5740 2040 pts/1 Ss 10:35 0:00 /bin/bash
root 50 0.0 0.0 9380 1464 pts/1 R+ 10:35 0:00 ps -aux
- 守护状态运行:可以使用-d参数让容器以守护状态运行
- 查看容器输出:使用
docker [container] logs
命令- -details:打印详细信息
- -f,-follow:保持持续输出
- -since string:输出从某个时间开始的日志
- -tail string:输出最近若干日志
- -t,timestamps:现实时间戳
- -until string:输出某个时间之前的日志
docker logs ce55f5ewf15
停止容器
- 暂停容器
- 使用
docker [container] pause CONTAINER [CONTAINER...]
命令暂停一个运行的容器 - 处于paused状态的容器可以使用
docker [container] unpause CONTAINER [CONTAINER...]
恢复运行
- 使用
- 终止容器
- 可以使用
docker [container] stop
终止一个容器,命令格式为docker [container] stop [-t|--time[=10]] [CONTAINER...]
- 该命令向容器发送SIGTERM信号,超时一段时间后发送SIGKILL终止容器
- 执行后使用
docker container prune
命令来清除所有处于停止状态的容器 - 也可以通过
docker [container] kill
直接发送SIGKILL信号终止容器 - 当Docker容器中指定的应用终结时,Docker容器也会终止
- 处于终止状态的容器,可以使用
docker [container] start
来重新启动 docker [container] restart
命令会先将容器终止,再重新启动
- 可以使用
进入容器
- 使用-d参数,容器启动后会进入后台,用户无法看到信息
- attach命令
- 格式
docker [container] attach [--detach-keys[=[]]] [--no-stdin] [--sig-proxy[=true]] CONTAINER
--detach-keys[=[]]
指定退出attach模式的快捷键序列,默认是CTRL-p,CTRL-q--no-stdin=true|false
是否关闭标准输入,默认打开--sig-proxy=true|false
是否代理收到的系统信号给应用进程,默认true- 然而使用attach命令有时不方便,当多个窗口同时attach同一个容器时,所有窗口会同步显示,一个窗口命令阻塞时,其他窗口也无法使用
- 格式
- exec命令
- Docker1.3开始,提供了一个exec命令,可以在运行中容器内直接执行任意命令
docker [container] exec [-d|--detach] [--detach-keys[=[]]] [-i|--interactive] [--privileged] [-t|--tty] [-u|--user[=USER]] CONTAINER COMMAND [ARG...]
- 比较重要的参数
- -d,—detach:在容器中后台执行命令
- —detach-keys=””:指定将容器切回后台的按键
- -e,—env=[]:指定环境变量列表
- -i,—interactive=true|false:打开标准输入接收用户输入命令,默认为false
- —privileged=true|false:是否给执行命令以最高权限,默认false
- -t,—tty=true|false:分配伪终端,默认false
- -u,—user=””:执行命令的用户名或ID
- 进入容器并启动bash:
docker exec -it ajfiweofew /bin/bash
删除容器
- 使用
docker [container] rm
命令删除处于终止或退出状态的容器 - 格式
docker [container] rm [-f|--force] [-l|--link] [-v|--volumes] CONTAINER
- 支持的选项
-f,--force=false
是否强行终止并删除运行中的容器-l,--link=false
删除容器的链接,但是保留容器-v,--volumes=false
删除容器挂载的数据卷
导入和导出容器
- 有些时候,需要把容器从一个系统迁移到另一个系统,此时可以利用容器的导入导出功能
- 容器导出
- 使用
docker [container] export
命令,无论容器是否在运行,都可以导出 - 例如
docker export -o test_tomcat.tar bjio56161b
- 使用
- 容器导入
- 使用
docker [container] import
命令,用户可以通过-c,—change=[]选项在导入同时执行对容器进行修改的Dockerfile指令 - 例如
docker import test_tomcat.tar - test/ubuntu:v1.0
- 使用
查看容器
- 查看容器详情
- 使用
docker container inspect [OPTIONS] CONTAINER [CONTAINER...]
- 使用
- 查看容器内进程
- 使用
docker [container] top [OPTIONS] CONTAINER
- 使用
- 查看统计信息
- 使用
docker [container] stats [OPTIONS] [CONTAINER...]
显示CPU,内存,网络等信息 - -a,-all:输出所有容器信息,默认仅在运行中的信息
- -format string:格式化输出信息
- -no-stream:不持续输出,默认实时输出
- -no-trunc:不截断输出
- 使用
其他容器命令
访问仓库
Docker Hub公共仓库镜像市场
- 仓库是集中存放镜像的地方,要区分仓库和注册服务器(Registry),注册服务器是存放仓库的具体服务器,一个注册服务器可以包含多个仓库,每个仓库可以下载某一类镜像
- 因此,仓库可以被看作一个具体的项目或目录,例如对于
private-docker.com/ubuntu
来说,private-docker.com
是注册服务器地址,ubuntu
是仓库名 - Docker Hub是Docker提供的公共镜像库
- 登录:使用
docker login
命令输入用户名,密码,邮箱完成注册和登录;注册成功后,本地用户目录下会自动创建.docker/config.json
文件,保存用户认证信息,登录成功后,就可以制作上传个人镜像了 基本操作
docker search
查找镜像docker pull
拉取镜像docker push
推送本地镜像到Docker Hub- 如下查找到的镜像中,分为两类
- 一种是类似centos的基础镜像,称为根镜像,往往由官方制作,以单个单词为名称
- 一种是ansible/centos7-ansible的镜像,代表是用户ansible维护的,以
user_name/centos
的形式命名;表明是该用户仓库下的镜像[root@izuf650sjqtwslsibvattnz ~]# docker search centos
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
centos The official build of CentOS. 6085 [OK]
ansible/centos7-ansible Ansible on Centos7 131 [OK]
consol/centos-xfce-vnc Centos container with "headless" VNC session… 117 [OK]
jdeathe/centos-ssh OpenSSH / Supervisor / EPEL/IUS/SCL Repos - … 115 [OK]
centos/systemd systemd enabled base container. 85 [OK]
centos/mysql-57-centos7 MySQL 5.7 SQL database server 77
imagine10255/centos6-lnmp-php56 centos6-lnmp-php56 58 [OK]
tutum/centos Simple CentOS docker image with SSH access 47
自动创建:可以自动跟随项目代码变更而重新构建镜像
第三方镜像市场
- 如果使用第三方仓库注册服务器,则需要在镜像名前面添加具体地址
- 格式为
index.tenxcloud.com/<namespace>/<repository>:<tag>
- 例如
docker pull index.tenxcloud.com/docker_library/node:latest
搭建私有镜像仓库Registry
- 使用Registry镜像搭建
docker run -d -p 5000:5000 registry
- 默认创建的容器,仓库会被放在容器的
/var/lib/registry
目录下,如果没有进入到容器中,无法使用该目录,可以通过-v参数将镜像文件夹存放到本地路径 docker run -d -p 9988:5000 -v /opt/data/registry:/var/lib/registry registry
- 接下来就可以使用上传和下载镜像的命令了
Docker数据管理
数据卷
- 生产中,往往需要对数据进行持久化,或者在多个容器中进行数据共享,容器中管理数据由两种方式
- 数据卷(Data Volumes):容器内数据直接映射到本地主机环境
- 数据卷容器(Data Volumes Containers):使用特定容器维护数据卷
- 数据卷是一个可供容器使用的特殊目录,它将主机操作系统目录直接映射进容器,类似Linux中的mount行为
- 创建数据卷:通过
volume
子命令来管理数据卷,通过docker volume create -d local test
创建数据卷,test数据卷会被创建在/var/lib/docker/volumes
下 - 其他命令,docker volumes还支持inspect(查看详细信息),ls(列出已有数据卷),prune(清理无用数据卷),rm(删除数据卷)等
绑定数据卷
- 除了使用volume子命令管理数据卷外,还可以在创建容器时将本机的目录挂载到容器内作为数据卷,这种创建数据卷的形式称为绑定数据卷
- 使用
docker [container] run
命令时,使用-mount选项来使用数据卷,该选项支持三种类型数据卷- volume:普通数据卷,映射到主机/var/lib/docker/volumes路径下
- bind:绑定数据卷,映射到主机指定目录下
- tmpfs:临时数据卷,只存在内存中
- 下面使用training/webapp镜像创建一个web容器,并创建一个数据卷挂载到容器的/opt/webapp目录
docker run -d -P --name web --mount type=bind, source=/webapp, destination=/opt/webapp training/webapp python app.py
- 该命令等价于
docker run -d -P --name web -v /webapp:/opt/webapp training/webapp python app.py
- 这样,在测试时,可以直接在本地数据卷修改数据,容器及时更新
- Docker挂载的数据卷默认权限为rw,可以通过ro指定为只读
docker run -d -P --name web -v /webapp:/opt/webapp:ro training/webapp python app.py
数据卷容器
如果要在多个容器间共享数据,最简单的方式是使用数据卷容器,数据卷容器也是一个容器,但是它的目的是专门提供数据卷给其他容器挂载
-
Run命令常用参数
-d,--detach=true|false
:容器在后台运行,默认是在前台,即信息都会输出到标准流-p,--publish=[]
:指定如何映射本到本地主机端口,例如-p hostPort:containerPort
-v|--volume[=[[HOST-dir:]container-dir[:options]]]
:挂在主机上的文件卷到容器内-P,--publish-all=true|false
:通过NAT机制将容器标记暴露的端口自动映射到本地主机的临时端口,加了这个参数后使用netstat -anp | grep proxy命令可以看到打开了一个端口;如果没有加-P或-p,那么在本机不会暴露任何端口--name=""
:指定容器的别名-i,--interactive=true|false
:保持标准输入打开,默认为false;就是把容器的输入重定向到当前标准输入,这样就可以和容器交互了;如果只用了-t,没有-i,那么只代表分配一个伪终端,这时会进入这个伪终端,但是无法输入,因为伪终端的输入和当前标准输入未绑定-t,--tty=true|false
:分配一个伪终端,如果只使用了-i,没有使用-t,那么代表绑定了标准输入流,但是并没有打开一个新终端。这时的终端默认是?,即不属于任何终端,但是可以进行交互输入。- 下面可以看到,由于多次执行了-t分配伪终端,但是没有绑定输入,所以无法退出该终端,导致伪终端数目一直增加
- 因此,对于那些运行完就会退出的容器,可以分配一个伪终端给他,但是不绑定输入流,这样就可以一直运行了