3 Docker 入门

首先,确保 Docker 就绪。在命令行运行 docker info ,看看 Docker 是否存在和正常。

运行第一个容器

docker run -i -t ubuntu /bin/bash

对命令产生疑问,可以使用docker help命令来查看命令说明

在第一条命令中,我们先告诉了 Docker 执行 docker run 命令,并指定了 -i -t 两个命令行参数。其中 -i 表示开启 STDIN,-t 表示 Docker 要为创建的容器分配一个伪 tty 终端。这样新创建的容器才能提供一个交互式 shell。

接下来,我们指明了使用 ubuntu 镜像来创建容器。ubuntu 镜像是一个常备镜像,可作为“基础(base)”镜像,类似的镜像还有 fedora、debian、centos,它们都是由 Docker 官方提供的,保存在 Docker Hub Registry 上。

实际上发生了什么?

  • 首先,Docker 在本地查找 ubuntu 镜像(由于我们没有指明镜像的版本,默认为最新版镜像 ubuntu:latest ),如果没有找到,就连接官方 Docker Hub Registry 查看 Docker Hub 中有没有 ubuntu 镜像。一旦找到就会下载到本地宿主机中。
  • 随后,Docker 在文件系统内用这个镜像创建了一个容器。容器拥有自己的网络、IP,以及一个用来和宿主机进行通信的桥接网络接口。
  • 最后,我们告诉 Docker 在新容器中要执行什么命令,例中我们执行了 /bin/bash 。当容器创建完毕,Docker 就会执行容器中的 /bin/bash 命令,就可以看到容器中的 shell 了。
root@10871b426af0:/#

容器命名

docker run --name my_ubuntu -i -t ubuntu /bin/bash

上述命令将会创建名为 my_ubuntu 的容器。一个合法的容器名只能包含以下字符:a-z、A-Z、0-9、下划线、句号、减号,用正则表达式表示为 [a-zA-Z0-9-_.](因为句号在正则表达式中为通配字符,所以请把 . 理解为转义后的句号)。

在 Docker 中可以用容器名、UUID 缩写、UUID 来唯一指定一个容器。但是推荐为容器命名,这样更加方便理解与管理。

容器的命名不可重复,如果试图创建和已有容器相同名称的新容器,命令会执行失败。可以先执行 docker rm 命令删除已有容器,再创建新容器。

查看容器

docker ps 命令可以显示当前正在运行的容器;如果指定参数 -a ,则可以显示所有容器;指定参数 -l ,则只显示最后一个启动的容器。还可以使用 docker ps -n x命令,它会显示最后x个容器,不论这些容器的运行状态如何。

启动停止的容器

docker startdocker restart 这两个命令,前者可以启动已经停止的容器,后者无论容器处于运行还是停止状态都可以重新启动容器。

类似地,docker create 命令可以创建一个容器,但不运行它。

附着到容器上

执行 docker attach 命令,可以附着到处于运行状态容器的会话上。如果用在上面的 ubuntu 容器,则会进入 shell,此时如果退出 shell,容器也将停止。

创建守护式容器

除了上述的交互式容器(interactive container),也可以创建长期运行的容器。守护式容器(daemonized container)没有交互式会话,适合运行应用程序和服务。

docker run 命令中指定 -d 参数,Docker 便会创建守护式容器放到后台运行。

docker run --name daemon_hello_world -d ubuntu /bin/sh -c "while true; do echo hello world; sleep 1; done" 

该命令创建了一个守护式容器,并于后台运行,运行后执行了循环打印 hello world 的命令。

看看容器内部在做什么

针对上面的例子,我们知道容器正在每隔1秒打印一条 hello world 日志。使用以下命令可以参看容器的日志:

docker logs daemon_hello_world

它将获取到最后的一些日志并返回。我们还可以对 docker logs 命令指定 -f 参数来跟踪打印日志,-t 参数用于显示日志的打印时间。可以这样指定参数 -ft

docker logs 命令还可以指定参数 --tail 7 表示只打印最后的7条日志。 下面我们结合使用一下:

docker logs --tail 3 -ft daemon_hello_world 这条命令就表示,立刻打印最近3条日志并跟踪打印日志,且每行打印都带有时间戳。

2019-03-11T16:34:38.962240900Z hello world
2019-03-11T16:34:39.963360400Z hello world
2019-03-11T16:34:40.964409500Z hello world
2019-03-11T16:34:41.964991100Z hello world
2019-03-11T16:34:42.966022100Z hello world
2019-03-11T16:34:43.967181500Z hello world

查看容器中的进程

docker top daemon_hello_world

执行结果:

PID                 USER                TIME                COMMAND
19039               root                0:00                /bin/sh -c while true; do echo hello world; sleep 1;done
19143               root                0:00                sleep 1  

Docker统计信息

docker stats

该命令可以显示一个或多个容器的统计信息。输出样式如下:

CONTAINER ID        NAME                CPU %               MEM USAGE / LIMIT     MEM %               NET I/O             BLOCK I/O           PIDS
6174c0b2ac26        daemon_hello_world  0.14%               968KiB / 1.934GiB     0.05%               928B / 0B           2.16MB / 0B         2
4dc6ef70adf6        redis               0.14%               1.977MiB / 1.934GiB   0.10%               3.38kB / 0B         8.53MB / 0B         4
658af9c3a304        mysql               8.12%               376.4MiB / 1.934GiB   19.00%              6.52MB / 29.4MB     113MB / 22.5MB      35
ce5da739a2a3        rabbitmq            0.33%               88.3MiB / 1.934GiB    4.46%               2.88kB / 0B         39.9MB / 123kB      88

在容器内运行进程

使用 docker exec 命令在新容器内额外启动新进程。容器内运行的进程有两种:后台任务和交互式任务(须保持在前台)。

docker exec -d daemon_hello_world touch /etc/new_config_file

上面的命令中 -d 表明要运行的是一个后台进程,命令在容器中新建了 /etc/new_config_file 空文件。

我们还可以使用命令 docker exec -i -t daemon_hello_world /bin/bash ,在 daemon_hello_world 容器中创建一个新的 bash 会话。

停止守护式容器

可以使用 docker stop 停止正在运行的容器。如果想快速停止容器,还可以使用 docker kill 命令。

docker stop 向容器进程发送 SIGTERM 新号。而 docker kill 向容器发送 SIGKILL 新号。

自动重启的容器

默认的容器是不会自动重启的,通过 --restart 标志,可以让 Docker 自动重新启动容器。

docker run --restart=always --name daemon_restart -d ubuntu /bin/sh -c "while true; do echo hello xxx; sleep 1; done"

上面的命令中 --restart 标志被设置为 always 。表示无论容器的退出代码是什么,Docker 都会自动重启该容器。还可以设置为 on-failure ,如此只有当退出码不为 0 的时候,才会重启;同时 on-failure 还接受一个重启次数可选参数,--restart=on-failure:5,没错这条命令表示当异常退出容器时,最多重启5次。

删除容器

可以使用 docker rm 来删除不用的容器。默认执行是不可以删除运行中的容器的,但是可以使用 -f 标志来强制删除正在运行的容器。
如果你想一次性删除所有的容器,可以使用以下命令

docker rm `docker ps -a -q`

注意:命令中的符号 ` 不是单引号,而是Tab键上方的那个反单引号,我第一次看的时候就看错了。
上面的命令中的 -q 表示只列出容器的 ID,如果对命令参数有什么疑问,可以使用help命令查看。比如上面这个命令中,我对-q标志有疑问,可以使用 docker help ps 来查看详细的命令说明。

深入容器

除了通过 docker ps 获取获取容器信息,还可以用 docker inspect 来获得更多的容器信息。

执行:docker inspect daemon_hello_world
结果:
[
    {
        "Id": "64ded64e3207d3583a19e1ac4d8ed86f6813e2d06764c7b618b3bb52911ac8ef",
        "Created": "2019-03-12T11:01:33.8559955Z",
        "Path": "/bin/sh",
        "Args": [
            "-c",
            "while true; do echo hello world; sleep 1; done"
        ],
        "State": {
            "Status": "running",
            "Running": true,
            "Paused": false,
            "Restarting": false,
            "OOMKilled": false,
            "Dead": false,
            "Pid": 6588,
            "ExitCode": 0,
            "Error": "",
            "StartedAt": "2019-03-12T11:01:34.5640346Z",
            "FinishedAt": "0001-01-01T00:00:00Z"
        },
        "Image": "sha256:47b19964fb500f3158ae57f20d16d8784cc4af37c52c49d3b4f5bc5eede49541",
        "ResolvConfPath": "/var/lib/docker/containers/64ded64e3207d3583a19e1ac4d8ed86f6813e2d06764c7b618b3bb52911ac8ef/resolv.conf",
        "HostnamePath": "/var/lib/docker/containers/64ded64e3207d3583a19e1ac4d8ed86f6813e2d06764c7b618b3bb52911ac8ef/hostname",
        "HostsPath": "/var/lib/docker/containers/64ded64e3207d3583a19e1ac4d8ed86f6813e2d06764c7b618b3bb52911ac8ef/hosts",
        "LogPath": "/var/lib/docker/containers/64ded64e3207d3583a19e1ac4d8ed86f6813e2d06764c7b618b3bb52911ac8ef/64ded64e3207d3583a19e1ac4d8ed86f6813e2d06764c7b618b3bb52911ac8ef-json.log",
        "Name": "/daemon_hello_world",
        "RestartCount": 0,
        "Driver": "overlay2",
        "Platform": "linux",
        "MountLabel": "",
        "ProcessLabel": "",
        "AppArmorProfile": "",
        "ExecIDs": null,
        "HostConfig": {
            "Binds": null,
            "ContainerIDFile": "",
            "LogConfig": {
                "Type": "json-file",
                "Config": {}
            },
            "NetworkMode": "default",
            "PortBindings": {},
            "RestartPolicy": {
                "Name": "always",
                "MaximumRetryCount": 0
            },
            "AutoRemove": false,
            "VolumeDriver": "",
            "VolumesFrom": null,
            "CapAdd": null,
            "CapDrop": null,
            "Dns": [],
            "DnsOptions": [],
            "DnsSearch": [],
            "ExtraHosts": null,
            "GroupAdd": null,
            "IpcMode": "shareable",
            "Cgroup": "",
            "Links": null,
            "OomScoreAdj": 0,
            "PidMode": "",
            "Privileged": false,
            "PublishAllPorts": false,
            "ReadonlyRootfs": false,
            "SecurityOpt": null,
            "UTSMode": "",
            "UsernsMode": "",
            "ShmSize": 67108864,
            "Runtime": "runc",
            "ConsoleSize": [
                50,
                120
            ],
            "Isolation": "",
            "CpuShares": 0,
            "Memory": 0,
            "NanoCpus": 0,
            "CgroupParent": "",
            "BlkioWeight": 0,
            "BlkioWeightDevice": [],
            "BlkioDeviceReadBps": null,
            "BlkioDeviceWriteBps": null,
            "BlkioDeviceReadIOps": null,
            "BlkioDeviceWriteIOps": null,
            "CpuPeriod": 0,
            "CpuQuota": 0,
            "CpuRealtimePeriod": 0,
            "CpuRealtimeRuntime": 0,
            "CpusetCpus": "",
            "CpusetMems": "",
            "Devices": [],
            "DeviceCgroupRules": null,
            "DiskQuota": 0,
            "KernelMemory": 0,
            "MemoryReservation": 0,
            "MemorySwap": 0,
            "MemorySwappiness": null,
            "OomKillDisable": false,
            "PidsLimit": 0,
            "Ulimits": null,
            "CpuCount": 0,
            "CpuPercent": 0,
            "IOMaximumIOps": 0,
            "IOMaximumBandwidth": 0,
            "MaskedPaths": [
                "/proc/asound",
                "/proc/acpi",
                "/proc/kcore",
                "/proc/keys",
                "/proc/latency_stats",
                "/proc/timer_list",
                "/proc/timer_stats",
                "/proc/sched_debug",
                "/proc/scsi",
                "/sys/firmware"
            ],
            "ReadonlyPaths": [
                "/proc/bus",
                "/proc/fs",
                "/proc/irq",
                "/proc/sys",
                "/proc/sysrq-trigger"
            ]
        },
        "GraphDriver": {
            "Data": {
                "LowerDir": "/var/lib/docker/overlay2/f84227ba5382db67d06e819a3a4c16230bb2dfa3f2daab5054c0935d79fd5c2a-init/diff:/var/lib/docker/overlay2/8a9e1bb011fe79aa7d9a139a55f4bc00fa9ede6e9ba877b23f20110b9dceb600/diff:/var/lib/docker/overlay2/430a6679897b4216a7b5cb76a32197aba98c6d539b08ee23bb23f0e9a3a070c6/diff:/var/lib/docker/overlay2/99d8f0e93a56d6b8147d50b09dd937a0fcc2d34a2a76f71b782cc7b27891d4ca/diff:/var/lib/docker/overlay2/585e92baad5fb64f4b3aa63992f39c8746be7f8c5429bef61257a9595738aa83/diff",
                "MergedDir": "/var/lib/docker/overlay2/f84227ba5382db67d06e819a3a4c16230bb2dfa3f2daab5054c0935d79fd5c2a/merged",
                "UpperDir": "/var/lib/docker/overlay2/f84227ba5382db67d06e819a3a4c16230bb2dfa3f2daab5054c0935d79fd5c2a/diff",
                "WorkDir": "/var/lib/docker/overlay2/f84227ba5382db67d06e819a3a4c16230bb2dfa3f2daab5054c0935d79fd5c2a/work"
            },
            "Name": "overlay2"
        },
        "Mounts": [],
        "Config": {
            "Hostname": "64ded64e3207",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "Tty": false,
            "OpenStdin": false,
            "StdinOnce": false,
            "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
            ],
            "Cmd": [
                "/bin/sh",
                "-c",
                "while true; do echo hello world; sleep 1; done"
            ],
            "Image": "ubuntu",
            "Volumes": null,
            "WorkingDir": "",
            "Entrypoint": null,
            "OnBuild": null,
            "Labels": {}
        },
        "NetworkSettings": {
            "Bridge": "",
            "SandboxID": "2cc78ade49335bcd8ea4e319b9a8623aae807e75d24dc8b62112b557710a9964",
            "HairpinMode": false,
            "LinkLocalIPv6Address": "",
            "LinkLocalIPv6PrefixLen": 0,
            "Ports": {},
            "SandboxKey": "/var/run/docker/netns/2cc78ade4933",
            "SecondaryIPAddresses": null,
            "SecondaryIPv6Addresses": null,
            "EndpointID": "d8e464ae9ea5f91625c24ca59898edb990cc9046f131345ec9ba39cfb0a870e0",
            "Gateway": "172.17.0.1",
            "GlobalIPv6Address": "",
            "GlobalIPv6PrefixLen": 0,
            "IPAddress": "172.17.0.5",
            "IPPrefixLen": 16,
            "IPv6Gateway": "",
            "MacAddress": "02:42:ac:11:00:05",
            "Networks": {
                "bridge": {
                    "IPAMConfig": null,
                    "Links": null,
                    "Aliases": null,
                    "NetworkID": "fb546420908ebd183567666f618142803234d185b401fbe1b7dd3500553c3a35",
                    "EndpointID": "d8e464ae9ea5f91625c24ca59898edb990cc9046f131345ec9ba39cfb0a870e0",
                    "Gateway": "172.17.0.1",
                    "IPAddress": "172.17.0.5",
                    "IPPrefixLen": 16,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "MacAddress": "02:42:ac:11:00:05",
                    "DriverOpts": null
                }
            }
        }
    }
]

docker inspect 还可以用 -f --format 标志选定查看结果,以及也可以同时指定多个容器。

执行:docker inspect -f '{{.NetworkSettings.IPAddress}}' daemon_hello_world redis mysql
结果:
172.17.0.5
172.17.0.2
172.17.0.3

至此,你学会了一些基本的 docker 命令,但是还没到能实用的地步,让我们继续下一篇吧。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 196,099评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,473评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 143,229评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,570评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,427评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,335评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,737评论 3 386
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,392评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,693评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,730评论 2 312
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,512评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,349评论 3 314
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,750评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,017评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,290评论 1 251
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,706评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,904评论 2 335