镜像
获取镜像
docker pull
拉取镜像
格式: docker pull [选项] [Docker Registry 地址[:端口号]/]仓库名[:标签]
- Docker Registry 地址:
<域名/IP>[:端口号]
, 默认地址为Docker Hub - 仓库名:用户名/软件名,在Docker Hub上,如果不写用户名,则默认为library(官方镜像)
docker run
以镜像启动并运行一个容器
格式:docker run [选项] 镜像标识 [启动后要执行命令] [参数...]
eg: docker run -it --rm -p 4000:80 ubuntu:18.04 bash
eg: docker run -it --rm -p 4000:80 ubuntu:18.04 ls
eg: docker run -d --rm -p 4000:80 ubuntu:18.04 ls
-
选项:
-
-it
:这是两个参数,-t 选项让Docker分配一个伪终端(pseudo-tty)并绑定到容器的标准输入上, -i 则让容器的标准输入保持打开。我们这里打算进入 bash 执行一些命令并查看返回结果,因此我们需要交互式终端。最后通过exit
退出,如果没有这个参数,则CRTL+C
退出 -
--rm
:容器退出后随之将其删除。 -
-d
:后台守护运行 -
-p
:将容器内的端口与主机绑定,将容器的80端口绑定到主机4000上 - 镜像标识:可以是镜像的名字+版本号,也可以是镜像的ID,如果没有版本号,则默认是:latest版本
-
如果是镜像的名字,并且本地没有,则会默认先执行docker pull将镜像下载再启动。
镜像查询
列出镜像
docker images
或者docker image ls
列表中只会显示顶层镜像,一般来说这些信息就够了
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
python 2.7-slim 99079b24ed51 12 days ago 120MB
node 10.15.1 8fc2110c6978 2 weeks ago 897MB
<none> <none> 7b25fb2216b1 2 days ago 1.08GB
nginx latest f09fe80eb0e7 2 weeks ago 109MB
仓库名
、标签
、镜像ID
、创建时间
和镜像体积
列表上镜像体积总和并非所有镜像实际硬盘消耗空间。因为docker镜像是多层存储,可以继承和复用,所以不同镜像可能使用相同的基础镜像,也就是共同层。
查看镜像占用空间
docker system df
$ docker system df
TYPE TOTAL ACTIVE SIZE RECLAIMABLE
Images 9 2 1.895GB 1.663GB (87%)
Containers 2 0 2B 2B (100%)
Local Volumes 0 0 0B 0B
Build Cache 0 0 0B 0B
虚悬镜像(dangling image)
一个特殊的镜像,这个镜像既没有仓库名,也没有标签,均为 <none>。
上面列表中的:
<none> <none> 7b25fb2216b1 2 days ago 1.08GB
这个镜像原本是有镜像名和标签,出现这种情况的原因:
- 随镜像维护,发布新版本后,重新
docker pull
时,这个镜像名被转移到新下载的镜像上,旧的镜像名称则被取消 -
docker build
时,由于新旧镜像同名,旧镜像的名称则被取消了
专门过滤查询
docker images -f dangling=true
$ docker images -f dangling=true
REPOSITORY TAG IMAGE ID CREATED SIZE
<none> <none> 7b25fb2216b1 2 days ago 1.08GB
一般来说,虚悬镜像已经失去了存在的价值,是可以随意删除的,可以用docker image prune
删除。
中间层镜像
默认的docker image ls
或者docker images
列表中只会显示顶层镜像,如果希望显示包括中间层镜像在内的所有镜像的话,需要加 -a 参数。
$ docker images -a
这样会看到很多无标签的镜像,与之前的虚悬镜像不同,这些无标签的镜像很多都是中间层镜像,是其它镜像所依赖的镜像。这些无标签镜像不应该删除,否则会导致上层镜像因为依赖丢失而出错
过滤查询镜像
docker images [参数或者条件]
- 根据仓库名列出镜像
$ docker images ubuntu
- 列出特定的某个镜像,也就是说指定仓库名和标签
$ docker image ls ubuntu:18.04
- 过滤器参数
--filter
或者-f
- 查询虚悬镜像:
-f dangling=true
- 查询在某个镜像建立之后的镜像:
-f since=ubuntu:18.04
- 之前:
-f before=ubuntu:18.04
- 如果镜像构建时,定义了
LABEL
,还可以通过LABEL
来过滤:label=com.example.version=0.1
- 查询虚悬镜像:
输出格式
- 只输出镜像ID
$ docker images -q
5f515359c7f8
05a60462f8ba
fe9198c04d62
- 自定义输出
# 包含镜像ID和仓库名
$ docker image ls --format "{{.ID}}: {{.Repository}}"
05a60462f8ba: nginx
00285df0df87: <none>
f753707788c5: ubuntu
f753707788c5: ubuntu
1e0c3dd64ccd: ubuntu
# 以表格等距显示,并且有标题行,和默认一样,不过自己定义列:
$ docker image ls --format "table {{.ID}}\t{{.Repository}}\t{{.Tag}}"
IMAGE ID REPOSITORY TAG
05a60462f8ba nginx latest
00285df0df87 <none> <none>
f753707788c5 ubuntu 18.04
f753707788c5 ubuntu latest
删除本地镜像
docker image rm
或者docker rmi
格式:docker image rm [选项] <镜像标识1> [<镜像标识2> ...]
镜像标识: 镜像ID,仓库名:标签,镜像摘要(太麻烦了,这个不常用)
删除行为
- Untagged 删除当前指向的标签,因为同一个镜像有多个标签,当删除所指定的标签后,可能别的标签指向了这个镜像,这是不会删除
- Deleted 真正删除
组合批量删除
# 删除仓库名为node的所有标签镜像
$ docker image rm $(docker image ls -q node)
# 删除创建ubuntu:18.04之前的所有
$ docker image rm $(docker image ls -q -f before=ubuntu:18.04)
镜像保存
类似于git commit
,不过一般不会使用,而是用写Dockerfile的形式生成。因为通过commit
生成的,会把每一层的操作都记录下来,包括一些不必要的操作,最后可能会导致镜像臃肿。
格式:docker commit [选项] <容器ID或者容器名> [仓库名[:标签]]
eg: docker commit --auhtor "XXX@xxx.com" --message "修改了什么" server nginx:test
用Dockerfile定制镜像
Dockerfile 是一个文本文件,其内包含了一条条的指令(Instruction),每一条指令构建一层,因此每一条指令的内容,就是描述该层应当如何构建。
- 在一个空白目录中,建立一个文本文件,命名为
Dockerfile
- Dockerfile内容为:
FROM nginx
RUN echo '<h1>hello world!</h1>' > /usr/share/nginx/html/index.html
- 构建镜像
格式:docker build [选项] <上下文路径或者URL或者tar压缩包>
eg: docker build -t nginx:test1 .
以当前目录为上下文构建名为nginx:test1的镜像
eg: docker build https://github.com/twang2218/gitlab-ce-zh.git#:11.1
这行命令指定了构建所需的 Git repo,并且指定默认的 master 分支,构建目录为 /11.1/,然后 Docker 就会自己去 git clone 这个项目、切换到指定分支、并进入到指定目录后开始构建。
eg: docker build http://server/context.tar.gz
如果所给出的 URL 不是个 Git repo,而是个 tar 压缩包,那么 Docker 引擎会下载这个包,并自动解压缩,以其作为上下文,开始构建。
上下文: 构建镜像时的基础目录,所有的构建所需文件都不能在这个上下文目录之外,在构建时会将上下文中的所有文件打包(除了
.dockerignore
中忽略的),同时在Dockerfile中的命令的默认相对路径会以这个上下文路径为基础,当然也不能超出这个目录默认读取的是当前执行命令的路径下名为
Dockerfile
的文件,也可以手动指定-f ../node.Dockerfile
容器
容器是独立运行的一个或一组应用,以及它们的运行态环境。
容器启动
新建并启动
docker run
命令,在获取镜像里面有,就不单说了
启动时的流程:
- 检查本地是否存在指定的镜像,不存在就从公有仓库下载
- 利用镜像创建并启动一个容器
- 分配一个文件系统,并在只读的镜像层外面挂载一层可读写层
- 从宿主主机配置的网桥接口中桥接一个虚拟接口到容器中去
- 从地址池配置一个 ip 地址给容器
- 执行用户指定的应用程序
- 执行完毕后容器被终止
启动已经终止的容器
格式:docker container start [选项] 容器标识1 [容器标识2...]
守护态运行
后台运行
增加参数-d
eg: docker run -d nginx
使用了-d
命令后,容器会在后台运行并不会把输出的结果 (STDOUT) 打印到宿主机上面(输出结果可以用docker logs
查看)。
docker container logs [容器ID或者容器名]
查看容器信息
docker container ls
守护态运行
容器是否会一直运行,与docker run
指定的命令有关,和-d
无关
eg:
# 不会一直运行的
$ docker run -d ubuntu:18.04 ls
b64f8e71882d26cffa34453284b40f73cbdc66054cd8a0ba79cb73092dc76726
$ docker logs b64f8e71882d26cffa34453284b40f73cbdc66054cd8a0ba79cb73092dc76726
bin
boot
dev
etc
...
# node index.js 是启一个服务,所以会保持运行在后台,如果没有-d就是保持运行在前台
$ docker run -d node node index.js
终止容器
除了在容器中关闭运行的应用来关闭容器外,也可以使用docker container stop
来终止,用户通过 exit 命令或 Ctrl+d 来退出终端时,所创建的容器立刻终止。
格式:docker container stop 容器标识
终止状态的容器可以用 docker container ls -a 命令看到
重新启动终止态容器
docker container start
启动处于终止状态的容器
重启容器
docker container restart
会将一个运行态的容器终止,然后再重新启动它。
进入容器
在使用 -d 参数时,容器启动后会进入后台。
某些时候需要进入容器进行操作,包括使用docker attach
命令或docker exec
命令,推荐使用 docker exec 命令
因为在attach
中,使用exit
会导致容器停止,而exec
不会
$ docker run -dit ubuntu
39ee1ddf67b9819fca8bbe71e15a131a6f4df18efabd229d199dabc744ce5be5
$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
39ee1ddf67b9 ubuntu:18.04 "/bin/bash" 36 seconds ago Up 35 seconds elegant_lumiere
# 没有-t时,没有分配伪终端,但是命令执行结果任然可以返回
$ docker exec -i 39ee1ddf67b9 bash
$ ls
bin
boot
dev
...
# 分配了伪终端
$ docker exec -it 39ee1ddf67b9 bash
root@39ee1ddf67b9:/#
容器的导入和导出
导出容器
导出容器快照
docker export
eg:
$ 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
eg:
$ cat ubuntu.tar | docker import - test/ubuntu:test1
$ docker image ls
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
test/ubuntu test1 9d37a6082e97 About a minute ago 171.3 MB
此外,也可以通过指定 URL 或者某个目录来导入
docker import http://example.com/exampleimage.tgz example/imagerepo
用户既可以使用docker load
来导入镜像存储文件到本地镜像库,也可以使用docker import
来导入一个容器快照到本地镜像库。这两者的区别在于容器快照文件将丢弃所有的历史记录和元数据信息(即仅保存容器当时的快照状态),而镜像存储文件将保存完整记录,体积也要大。此外,从容器快照文件导入时可以重新指定标签等元数据信息。
删除容器
删除终止状态的容器
docker container rm
$ docker container rm test
test
如果需要删除运行中的容器,需要加一个-f
的参数
清理所有处于终止状态的容器
docker container prune
容器间通信
新建网络
$ docker network create -d bridge web
a0ff52c9783cf21da40c2c62ed81765d165658e591b04f7e1c139fe689f4fe9e
$ docker network ls
NETWORK ID NAME DRIVER SCOPE
a0ff52c9783c web bridge local
创建一个名为web的网络
-d
指定网络类型,有bridge
和overlay
。其中overlay
用于Swarm mode
将容器连接到网络上
运行一个容器并连接到新建的网络上
$ docker run -it --rm --name node1 --network web node sh
再开一个新终端
$ docker run -it --rm --name node2 --network web node sh
再开一个终端
$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f2b50d6261a7 node "node" 26 seconds ago Up 25 seconds node2
da2b12415ff8 node "node" About a minute ago Up About a minute node1
连接测试
在node1中
$ ping node2
PING node2 (172.25.0.3) 56(84) bytes of data.
64 bytes from node2.web (172.25.0.3): icmp_seq=1 ttl=64 time=0.148 ms
64 bytes from node2.web (172.25.0.3): icmp_seq=2 ttl=64 time=0.168 ms
在node2中
$ ping node1
PING node1 (172.25.0.2) 56(84) bytes of data.
64 bytes from node1.web (172.25.0.2): icmp_seq=1 ttl=64 time=0.199 ms
64 bytes from node1.web (172.25.0.2): icmp_seq=2 ttl=64 time=0.174 ms
Docker Compose
通过一个单独的 docker-compose.yml 模板文件(YAML 格式)来定义一组相关联的应用容器为一个项目(project)
Compose 中有两个重要的概念:
服务 (service):一个应用的容器,实际上可以包括若干运行相同镜像的容器实例。
项目 (project):由一组关联的应用容器组成的一个完整业务单元,在 docker-compose.yml 文件中定义。
Compose 的默认管理对象是项目,通过子命令对项目中的一组容器进行便捷地生命周期管理。
基础使用
web应用
新建文件夹,在其中创建server.js
const http = require('http')
const app = http.createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'text/html;charset=utf-8' })
console.log(`<h1>【${req.method}】: ${req.url}</h1>`)
const resText = `<h1>【${req.method}】: ${req.url}</h1>`
res.end(resText)
})
app.listen(4000)
Dockerfile
FROM node
ADD . /web
WORKDIR /web
RUN npm config set registry http://registry.npm.taobao.org/ \
&& npm install
CMD ["node", "./server.js"]
docker-compose.yml
version: "3"
services:
web:
container_name: web
build:
context: ./
dockerfile: Dockerfile
port:
- "4001:4000"
运行compose
$ docker-compose up
Compose 命令
命令格式
$ docker-compose [-f=<arg>...] [options] [COMMAND] [ARGS...]
命令选项
-f, --file
指定使用的Compose模板文件,默认为当前目录的docker-compose.yml,可以多次指定-p, --project-name
指定项目别名,默认将使用所在目录名称作为项目名--x-networking
使用Docker的可拔插网络后端特性--x-network-driver
指定网络后端的驱动,默认为bridge
--verbose
输出更多调试信息-v, --version
打印版本并退出
相关命令使用
build
格式:docker-compose build [options] [SERVICE...]
构建(重新构建)项目中的服务容器。
服务容器一旦构建后,将会带上一个标记名
可以随时在项目目录下运行 docker-compose build 来重新构建服务。
选项:
--force-rm
删除构建过程中的临时容器--no-cache
构建镜像过程中不使用cache(会使构建过程时间变长)--pull
始终尝试通过pull来获取更新版本的镜像
config
验证 Compose 文件格式是否正确,若正确则显示配置,若格式错误显示错误原因。
down
此命令将会停止 up 命令所启动的容器,并移除网络
exec
进入指定的容器。
images
列出 Compose 文件中包含的镜像。
kill
格式:docker-compose kill [options] [SERVICE...]
logs
格式:docker-compose logs [options] [SERVICE...]
查看服务容器的输出。默认情况下,docker-compose 将对不同的服务输出使用不同的颜色来区分。可以通过--no-color
来关闭颜色。
pause
格式:docker-compose pause [SERVICE...]
暂停一个服务容器。
ps
格式:docker-compose ps [options] [SERVICE...]
列出项目中目前的所有容器。
选项:
-
-q
只打印容器的 ID 信息。
pull
格式:docker-compose pull [options] [SERVICE...]
拉取服务依赖的镜像
选项:
-
--ignore-pull-failures
忽略拉取镜像过程中的错误。
push
推送服务依赖的镜像到 Docker 镜像仓库。
restart
格式:docker-compose restart [options] [SERVICE...]
重启项目中的服务
选项:
-
-t, --timeout
指定重启前停止容器的超时(默认为10秒)
rm
格式:docker-compose rm [options] [SERVICE...]
删除所有(停止状态的)服务容器。推荐先执行 docker-compose stop 命令来停止容器。
选项:
-
-f, --force
强制直接删除,包括非停止状态的容器。一般尽量不要使用该选项。 -
-v
删除容器所挂载的数据卷
run
格式:docker-compose run [options] [-p PORT...] [-e KEY=VAL...] SERVICE [COMMAND] [ARGS...]
在指定服务上执行一个命令。
eg:
$ docker-compose run ubuntu ping www.baidu.com
默认情况下,如果存在关联,则所有关联的服务将会自动被启动,除非这些服务已经在运行中。
如果不希望自动启动关联的容器,可以使用 --no-deps 选项,将不会启动 web 容器所关联的其它容器。
$ docker-compose run --no-deps web python manage.py shell
该命令类似启动容器后运行指定的命令,相关卷、链接等等都将会按照配置自动创建。
与启动容器后运行指定的命令不同点:
给定命令将会覆盖原有的自动运行命令;
不会自动创建端口,以避免冲突。
选项:
-d
后台运行容器--name
为容器起一个别名--entrypoint
覆盖默认的容器启动指令(CMD)-e KEY=VAL
设置环境变量值,可多次使用选项设置多个环境-u, --user=""
指定运行容器的用户名或者uid--no-deps
不自动启动关联的服务容器--rm
运行命令后自动删除容器,-d
模式下忽略-p, --publish=[]
映射容器端口到本地主机--service-ports
配置服务端口并映射到本地主机
scale
格式:docker-compose scale [options] [SERVICE=NUM...]
设置指定服务运行的容器个数。
通过 service=num 的参数来设置数量。
eg:
$ docker-compose scale web=3 db=2
将启动 3 个容器运行 web 服务,2 个容器运行 db 服务。
一般的,当指定数目多于该服务当前实际运行容器,将新创建并启动容器;反之,将停止容器。
选项:
-
-t, --timeout
停止容器时候的超时(默认10秒)
start
格式:docker-compose start [SERVICE...]
启动已经存在的服务容器。
stop
格式:docker-compose stop [options] [SERVICE...]
停止已经处于运行状态的容器,但不删除它。通过 docker-compose start 可以再次启动这些容器。
选项:
-
-t
同上
top
查看各个服务容器内运行的进程
unpause
格式:docker-compose unpause [SERVICE...]
恢复处于暂停状态中的服务。
up
格式:docker-compose up [options] [SERVICE...]
该命令十分强大,它将尝试自动完成包括构建镜像,(重新)创建服务,启动服务,并关联服务相关容器的一系列操作。
链接的服务都将会被自动启动,除非已经处于运行状态。
可以说,大部分时候都可以直接通过该命令来启动一个项目。
默认情况,docker-compose up
启动的容器都在前台,控制台将会同时打印所有容器的输出信息,可以很方便进行调试。
当通过Ctrl-C
停止命令时,所有容器将会停止。
如果使用docker-compose up -d
,将会在后台启动并运行所有的容器。一般推荐生产环境下使用该选项。
默认情况,如果服务容器已经存在,docker-compose up
将会尝试停止容器,然后重新创建(保持使用volumes-from
挂载的卷),以保证新启动的服务匹配docker-compose.yml
文件的最新内容。如果用户不希望容器被停止并重新创建,可以使用docker-compose up --no-recreate
。这样将只会启动处于停止状态的容器,而忽略已经运行的服务。如果用户只想重新部署某个服务,可以使用docker-compose up --no-deps -d <SERVICE_NAME>
来重新创建服务并后台停止旧服务,启动新服务,并不会影响到其所依赖的服务。
选项:
-d
在后台运行服务容器--no-color
不使用颜色来区分不同的服务的控制台输出--no-deps
不启动服务所链接的容器--force-recreate
强制重新创建容器,不能与--no-recreate
同时使用--no-recreate
如果容器已经存在,则不重新创建,不能与--force-recreate
同时使用--no-build
不自动构建缺失的服务镜像-t, --timeout
同上
version
格式:docker-compose version
打印版本信息