一、docker 安装
1、获取最新版本的 Docker 安装包
$ sudo apt-get update
$ sudo apt-get install -y docker.io
2、查看docker的版本号
root@jason-virtual-machine:~# docker version
Client version: 1.6.2
Client API version: 1.18
Go version (client): go1.2.1
Git commit (client): 7c8fca2
OS/Arch (client): linux/amd64
Server version: 1.6.2
Server API version: 1.18
Go version (server): go1.2.1
Git commit (server): 7c8fca2
OS/Arch (server): linux/amd64
docker的虚拟网桥
root@jason-virtual-machine:~# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 00:0c:29:2a:10:85 brd ff:ff:ff:ff:ff:ff
inet 192.168.226.136/24 brd 192.168.226.255 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::20c:29ff:fe2a:1085/64 scope link
valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 56:84:7a:fe:97:99 brd ff:ff:ff:ff:ff:ff
inet 172.17.42.1/16 scope global docker0
valid_lft forever preferred_lft forever
二、启动docker 后台服务
sudo service docker start
三、docker 容器的使用
(1)Docker Hello World
Docker 允许你在容器内运行应用程序, 使用 docker run 命令来在容器内运行一个应用程序。
输出Hello world
root@jason-virtual-machine:~# docker run ubuntu:15.10 /bin/echo "Hello world"
Hello world
各个参数解析:
-
docker: Docker 的二进制执行文件。
-
run:与前面的 docker 组合来运行一个容器。
-
ubuntu:15.10指定要运行的镜像,Docker首先从本地主机上查找镜像是否存在,如果不存在,Docker 就会从镜像仓库 Docker Hub 下载公共镜像。
-
/bin/echo "Hello world": 在启动的容器里执行的命令
以上命令完整的意思可以解释为:Docker 以 ubuntu15.10 镜像创建一个新容器,然后在容器里执行 bin/echo "Hello world",然后输出结果。
当利用 docker run
来创建容器时,Docker 在后台运行的标准操作包括:
- 检查本地是否存在指定的镜像,不存在就从公有仓库下载
- 利用镜像创建并启动一个容器
- 分配一个文件系统,并在只读的镜像层外面挂载一层可读写层
- 从宿主主机配置的网桥接口中桥接一个虚拟接口到容器中去
- 从地址池配置一个 ip 地址给容器
- 执行用户指定的应用程序
- 执行完毕后容器被终止
(2)运行交互式的容器
我们通过docker的两个参数 -i -t,让docker运行的容器实现"对话"的能力
runoob@runoob:~$ docker run -i -t ubuntu:15.10 /bin/bash
root@dc0050c79503:/#
各个参数解析:
-
-t:在新容器内指定一个伪终端或终端。
-
-i:允许你对容器内的标准输入 (STDIN) 进行交互。
此时我们已进入一个 ubuntu15.10系统的容器
我们尝试在容器中运行命令 cat /proc/version和ls分别查看当前系统的版本信息和当前目录下的文件列表
root@jason-virtual-machine:~# docker run -i -t ubuntu:15.10 /bin/bash
root@4dfd6620eb93:/# cat /proc/version
Linux version 3.16.0-30-generic (buildd@kissel) (gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) ) #40~14.04.1-Ubuntu SMP Thu Jan 15 17:43:14 UTC 2015
root@4dfd6620eb93:/# ls
bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
root@4dfd6620eb93:/# exit
root@jason-virtual-machine:~# docker run ubuntu:15.10 /bin/echo "Hello world"
Hello world
root@jason-virtual-machine:~# docker run -i -t ubuntu:15.10 /bin/bash
root@d83d21c6c4e4:/# cat /proc/version
Linux version 3.16.0-30-generic (buildd@kissel) (gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) ) #40~14.04.1-Ubuntu SMP Thu Jan 15 17:43:14 UTC 2015
root@d83d21c6c4e4:/# ls
bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
root@d83d21c6c4e4:/# exit
exit
root@jason-virtual-machine:~#
我们可以通过运行exit命令或者使用CTRL+D来退出容器。
(3)启动容器(后台模式)
使用以下命令创建一个以进程方式运行的容器
root@jason-virtual-machine:~# docker run -d ubuntu:15.10 /bin/sh -c "while true; do echo hello world; sleep 1; done"
a7f6d1d7b0cf5e049242f4128b43dd2be1d197b16ab55dcdacc95991a5e3b19a
root@jason-virtual-machine:~#
在输出中,我们没有看到期望的"hello world",而是一串长字符
a7f6d1d7b0cf5e049242f4128b43dd2be1d197b16ab55dcdacc95991a5e3b19a
这个长字符串叫做容器ID,对每个容器来说都是唯一的,我们可以通过容器ID来查看对应的容器发生了什么。
首先,我们需要确认容器有在运行,可以通过 docker ps 来查看
root@jason-virtual-machine:~# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a7f6d1d7b0cf ubuntu:15.10 "/bin/sh -c 'while t 59 seconds ago Up 58 seconds stupefied_rosalind
root@jason-virtual-machine:~#
CONTAINER ID:容器ID
NAMES:自动分配的容器名称
在容器内使用docker logs命令,查看容器内的标准输出
root@jason-virtual-machine:~# docker logs a7f6d1d7b0cf
hello world
hello world
hello world
hello world
hello world
hello world
hello world
hello world
(4)停止容器
可以使用 docker container stop
来终止一个运行中的容器。
此外,当 Docker 容器中指定的应用终结时,容器也自动终止。
例如对于上一章节中只启动了一个终端的容器,用户通过 exit
命令或 Ctrl+d
来退出终端时,所创建的容器立刻终止。
终止状态的容器可以用 docker container ls -a
命令看到。例如
docker container ls -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ba267838cc1b ubuntu:18.04 "/bin/bash" 30 minutes ago Exited (0) About a minute ago trusting_newton
98e5efa7d997 training/webapp:latest "python app.py" About an hour ago Exited (0) 34 minutes ago backstabbing_pike
处于终止状态的容器,可以通过 docker container start
命令来重新启动。
此外,docker container restart
命令会将一个运行态的容器终止,然后再重新启动它。
我们使用 docker stop 命令来停止容器:
通过docker ps查看,容器已经停止工作:
root@jason-virtual-machine:~# docker stop a7f6d1d7b0cf
a7f6d1d7b0cf
root@jason-virtual-machine:~# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
root@jason-virtual-machine:~#
也可以用下面的命令来停止:
(5)启动已终止容器
可以利用 docker container start
命令,直接将一个已经终止的容器启动运行。
容器的核心为所执行的应用程序,所需要的资源都是应用程序运行所必需的。除此之外,并没有其它的资源。可以在伪终端中利用 ps
或 top
来查看进程信息。
(6)进入容器
在使用 -d
参数时,容器启动后会进入后台。
某些时候需要进入容器进行操作,包括使用 docker attach
命令或 docker exec
命令,推荐大家使用 docker exec
命令,原因会在下面说明。
attach
命令
下面示例如何使用 docker attach
命令。
$ 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,会导致容器的停止。
exec
命令
-i -t 参数
docker exec
后边可以跟多个参数,这里主要说明 -i
-t
参数。
只用 -i
参数时,由于没有分配伪终端,界面没有我们熟悉的 Linux 命令提示符,但命令执行结果仍然可以返回。
当 -i
-t
参数一起使用时,则可以看到我们熟悉的 Linux 命令提示符。
$ 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 -it 69d1 bash
root@69d137adef7a:/#
如果从这个 stdin 中 exit,不会导致容器的停止。这就是为什么推荐大家使用 docker exec
的原因。
(7)导出和导入容器
导出容器
如果要导出本地某个容器,可以使用 docker export
命令。
$ 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
从容器快照文件中再导入为镜像,例如
$ 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 或者某个目录来导入,例如
$ docker import http://example.com/exampleimage.tgz example/imagerepo
(8)删除容器
可以使用 docker container rm
来删除一个处于终止状态的容器。例如
$ docker container rm trusting_newton
trusting_newton
如果要删除一个运行中的容器,可以添加 -f
参数。Docker 会发送 SIGKILL
信号给容器。
(9)清理所有处于终止状态的容器
用 docker container ls -a
命令可以查看所有已经创建的包括终止状态的容器,如果数量太多要一个个删除可能会很麻烦,用下面的命令可以清理掉所有处于终止状态的容器。
$ docker container prune
四、docker客户端
docker 客户端非常简单 ,我们可以直接输入 docker 命令来查看到 Docker 客户端的所有命令选项。
可以通过命令 docker command --help 更深入的了解指定的 Docker 命令使用方法。
例如我们要查看 docker stats 指令的具体使用方法:
root@jason-virtual-machine:~# docker stats --help
Usage: docker stats [OPTIONS] CONTAINER [CONTAINER...]
Display a live stream of one or more containers' resource usage statistics
--help=false Print usage
(1)运行一个web应用
我们将在docker容器中运行一个 Python Flask 应用来运行一个web应用。
root@jason-virtual-machine:~# docker pull training/webapp //载入镜像
latest: Pulling from training/webapp
e9e06b06e14c: Already exists
a82efea989f9: Already exists
37bea4ee0c81: Already exists
07f8e8c5e660: Already exists
23f0158a1fbe: Already exists
0a4852b23749: Already exists
7d0ff9745632: Already exists
99b0d955e85d: Already exists
33e109f2ff13: Already exists
cc06fd877d54: Already exists
b1ae241d644a: Already exists
b37deb56df95: Already exists
02a8815912ca: Already exists
Digest: sha256:06e9c1983bd6d5db5fba376ccd63bfa529e8d02f23d5079b8f74a616308fb11d
Status: Image is up to date for training/webapp:latest
root@jason-virtual-machine:~# docker run -d -P training/webapp python app.py
be1bb913a3056bd5c8711429673cb8a1f517b53430581d3ba0345dd36a9b422a
root@jason-virtual-machine:~#
参数说明:
-
-d:让容器在后台运行。
-
-P:将容器内部使用的网络端口映射到我们使用的主机上。
(2)查看 WEB 应用容器
使用 docker ps 来查看我们正在运行的容器:
root@jason-virtual-machine:~# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
be1bb913a305 training/webapp:latest "python app.py" About a minute ago Up About a minute 0.0.0.0:32768->5000/tcp serene_hoover
root@jason-virtual-machine:~#
这里多了端口信息。
Docker 开放了 5000 端口(默认 Python Flask 端口)映射到主机端口 32769 上。
这时我们可以通过浏览器访问WEB应用:
我们也可以通过 -p 参数来设置不一样的端口:
root@jason-virtual-machine:~# docker run -d -p 5000:5000 training/webapp python app.py
3154b036b905c6a451464c4cadcce570658868db4ec8048ba161ee7af4a62b16
root@jason-virtual-machine:~# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3154b036b905 training/webapp:latest "python app.py" 3 seconds ago Up 2 seconds 0.0.0.0:5000->5000/tcp berserk_rosalind
be1bb913a305 training/webapp:latest "python app.py" 6 minutes ago Up 6 minutes 0.0.0.0:32768->5000/tcp serene_hoover
root@jason-virtual-machine:~#
容器内部的 5000 端口映射到我们本地主机的 5000 端口上。
(3)查看 WEB 应用程序日志
docker logs [ID或者名字] 可以查看容器内部的标准输出。
root@jason-virtual-machine:~# docker logs -f 3154b036b905
* Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
192.168.226.1 - - [04/Jul/2019 14:06:37] "GET / HTTP/1.1" 200 -
192.168.226.1 - - [04/Jul/2019 14:06:38] "GET /favicon.ico HTTP/1.1" 404 -
-f: 让 docker logs 像使用 tail -f 一样来输出容器内部的标准输出。
从上面,我们可以看到应用程序使用的是 5000 端口并且能够查看到应用程序的访问日志。
(4)查看WEB应用程序容器的进程
我们还可以使用 docker top 来查看容器内部运行的进程:
root@jason-virtual-machine:~# docker top berserk_rosalind
UID PID PPID C STIME TTY TIME CMD
root 5804 1668 0 22:05 ? 00:00:00 python app.py
root@jason-virtual-machine:~#
(5)检查 WEB 应用程序
使用 docker inspect 来查看 Docker 的底层信息。它会返回一个 JSON 文件记录着 Docker 容器的配置和状态信息。
root@jason-virtual-machine:~# docker inspect berserk_rosalind
[{
"AppArmorProfile": "",
"Args": [
"app.py"
],
"Config": {
"AttachStderr": false,
"AttachStdin": false,
"AttachStdout": false,
"Cmd": [
"python",
"app.py"
],
"CpuShares": 0,
"Cpuset": "",
"Domainname": "",
"Entrypoint": null,
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
],
"ExposedPorts": {
"5000/tcp": {}
},
(6)停止 WEB 应用容器
root@jason-virtual-machine:~# docker stop berserk_rosalind
berserk_rosalind
(7)重启WEB应用容器
已经停止的容器,我们可以使用命令 docker start 来启动。
docker ps -l 查询最后一次创建的容器:
root@jason-virtual-machine:~# docker start berserk_rosalind
berserk_rosalind
root@jason-virtual-machine:~# docker ps -l
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3154b036b905 training/webapp:latest "python app.py" 8 minutes ago Up 24 seconds 0.0.0.0:5000->5000/tcp berserk_rosalind
root@jason-virtual-machine:~#
正在运行的容器,我们可以使用 docker restart 命令来重启
(8)移除WEB应用容器
我们可以使用 docker rm 命令来删除不需要的容器
root@jason-virtual-machine:~# docker stop berserk_rosalind
berserk_rosalind
root@jason-virtual-machine:~# docker rm berserk_rosalind
berserk_rosalind
root@jason-virtual-machine:~# docker stop serene_hoover
serene_hoover
root@jason-virtual-machine:~# docker rm serene_hoover
serene_hoover
root@jason-virtual-machine:~# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
root@jason-virtual-machine:~#
五、Docker 镜像使用
当运行容器时,使用的镜像如果在本地中不存在,docker 就会自动从 docker 镜像仓库中下载,默认是从 Docker Hub 公共镜像源下载。
下面我们来学习:
- 1、管理和使用本地 Docker 主机镜像
- 2、创建镜像
(1)列出镜像列表
我们可以使用 docker images 来列出本地主机上的镜像。
root@jason-virtual-machine:~# docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
centos 6.7 ff5b7f1a99b5 3 months ago 190.6 MB
hello-world latest 9f5834b25059 6 months ago 1.84 kB
ubuntu 15.10 bfaaabeea063 2.950570 years ago 137.2 MB
training/webapp latest 02a8815912ca 4.139374 years ago 348.8 MB
root@jason-virtual-machine:~#
各个选项说明:
- REPOSTITORY:表示镜像的仓库源
- TAG:镜像的标签
- IMAGE ID:镜像ID
- CREATED:镜像创建时间
- SIZE:镜像大小
(2)获取一个新的镜像
当我们在本地主机上使用一个不存在的镜像时 Docker 就会自动下载这个镜像。如果我们想预先下载这个镜像,我们可以使用 docker pull 命令来下载它。
(3)查找镜像
我们可以从 Docker Hub 网站来搜索镜像,Docker Hub 网址为:https://hub.docker.com/
我们也可以使用 docker search 命令来搜索镜像。比如我们需要一个httpd的镜像来作为我们的web服务。我们可以通过 docker search 命令搜索 httpd 来寻找适合我们的镜像。
NAME:镜像仓库源的名称
DESCRIPTION:镜像的描述
OFFICIAL:是否docker官方发布
(4)拖取镜像
我们决定使用上图中的httpd 官方版本的镜像,使用命令 docker pull 来下载镜像。
root@jason-virtual-machine:/home/jason# docker pull httpd
latest: Pulling from httpd
19dcfa542d53: Pull complete
92df1cdf3097: Pull complete
4f1f4fe6a13e: Pull complete
46ef5e1a3144: Pull complete
da94146bda58: Pull complete
18d446ed215f: Pull complete
d1089d676a1f: Pull complete
0e4ce46a247c: Pull complete
38a12970d25b: Pull complete
fd1a669b9084: Already exists
fed72abac507: Already exists
658c4ff367db: Already exists
d91e3a0a9d04: Already exists
f70f353bccaa: Already exists
ecdfc87df13a: Already exists
Digest: sha256:bd8f6e1df9c6ba4048a7ac081499618c54bc9adf62cf976e857dee3b84ec75fe
Status: Downloaded newer image for httpd:latest
下载完成后,我们就可以使用这个镜像了。
w3cschool@w3cschool:~$ docker run httpd
(5)删除本地镜像
如果要删除本地的镜像,可以使用 docker image rm
命令,其格式为:
$ docker image rm [选项] <镜像1> [<镜像2> ...]
其中,<镜像>
可以是 镜像短 ID
、镜像长 ID
、镜像名
或者 镜像摘要
。
六、Docker 数据管理
在容器中管理数据主要有两种方式:
-
数据卷(Volumes)
-
挂载主机目录 (Bind mounts)
(1)数据卷
数据卷
是一个可供一个或多个容器使用的特殊目录,它绕过 UFS,可以提供很多有用的特性:
-
数据卷
可以在容器之间共享和重用 -
对
数据卷
的修改会立马生效 -
对
数据卷
的更新,不会影响镜像 -
数据卷
默认会一直存在,即使容器被删除
注意:
数据卷
的使用,类似于 Linux 下对目录或文件进行 mount,镜像中的被指定为挂载点的目录中的文件会隐藏掉,能显示看的是挂载的数据卷
。
创建一个数据卷
$ docker volume create my-vol
查看所有的 数据卷
$ docker volume ls
local my-vol
在主机里使用以下命令可以查看指定 数据卷
的信息
$ docker volume inspect my-vol
[
{
"Driver": "local",
"Labels": {},
"Mountpoint": "/var/lib/docker/volumes/my-vol/_data",
"Name": "my-vol",
"Options": {},
"Scope": "local"
}
]
启动一个挂载数据卷的容器
在用 docker run
命令的时候,使用 --mount
标记来将 数据卷
挂载到容器里。在一次 docker run
中可以挂载多个 数据卷
。
下面创建一个名为 web
的容器,并加载一个 数据卷
到容器的 /webapp
目录。
$ docker run -d -P \
--name web \
# -v my-vol:/wepapp \
--mount source=my-vol,target=/webapp \
training/webapp \
python app.py
查看数据卷的具体信息
在主机里使用以下命令可以查看 web
容器的信息
$ docker inspect web
数据卷
信息在 "Mounts" Key 下面
"Mounts": [
{
"Type": "volume",
"Name": "my-vol",
"Source": "/var/lib/docker/volumes/my-vol/_data",
"Destination": "/app",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
}
],
删除数据卷
$ docker volume rm my-vol
数据卷
是被设计用来持久化数据的,它的生命周期独立于容器,Docker 不会在容器被删除后自动删除 数据卷
,并且也不存在垃圾回收这样的机制来处理没有任何容器引用的 数据卷
。如果需要在删除容器的同时移除数据卷。可以在删除容器的时候使用 docker rm -v
这个命令。
删除数据卷要在容器stop并且被删除之后才可以进行
无主的数据卷可能会占据很多空间,要清理请使用以下命令
$ docker volume prune
(2)挂载主机目录
挂载一个主机目录作为数据卷
使用 --mount
标记可以指定挂载一个本地主机的目录到容器中去。
$ docker run -d -P \
--name web \
# -v /src/webapp:/opt/webapp \
--mount type=bind,source=/src/webapp,target=/opt/webapp \
training/webapp \
python app.py
上面的命令加载主机的 /src/webapp
目录到容器的 /opt/webapp
目录。这个功能在进行测试的时候十分方便,比如用户可以放置一些程序到本地目录中,来查看容器是否正常工作。本地目录的路径必须是绝对路径,以前使用 -v
参数时如果本地目录不存在 Docker 会自动为你创建一个文件夹,现在使用 --mount
参数时如果本地目录不存在,Docker 会报错。
Docker 挂载主机目录的默认权限是 读写
,用户也可以通过增加 readonly
指定为 只读
。
$ docker run -d -P \
--name web \
# -v /src/webapp:/opt/webapp:ro \
--mount type=bind,source=/src/webapp,target=/opt/webapp,readonly \
training/webapp \
python app.py
加了 readonly
之后,就挂载为 只读
了。如果你在容器内 /opt/webapp
目录新建文件,会显示如下错误
/opt/webapp # touch new.txt
touch: new.txt: Read-only file system
查看数据卷的具体信息
在主机里使用以下命令可以查看 web
容器的信息
$ docker inspect web
挂载主机目录
的配置信息在 "Mounts" Key 下面
"Mounts": [
{
"Type": "bind",
"Source": "/src/webapp",
"Destination": "/opt/webapp",
"Mode": "",
"RW": true,
"Propagation": "rprivate"
}
],
挂载一个本地主机文件作为数据卷
--mount
标记也可以从主机挂载单个文件到容器中
$ docker run --rm -it \
# -v $HOME/.bash_history:/root/.bash_history \
--mount type=bind,source=$HOME/.bash_history,target=/root/.bash_history \
ubuntu:18.04 \
bash
root@2affd44b4667:/# history
1 ls
2 diskutil list
这样就可以记录在容器输入过的命令了。