Docker学习笔记(二):简单使用

通过Docker命令行客户端使用Docker的一些例子



命令格式

Docker安装过程参考官网, 安装成功后我们可以通过命令行接口(CLI)来使用Docker, 每个命令都可能会包含一些标记(flags)和参数(arguments), 命令的格式大致如下:

$ [sudo] docker [subcommand] [flags] [arguments] ..

比如刚安装完成可以查看Docker的版本信息:

$ docker version

我们可以通过--help标记来获取帮助, 比如列出docker命令的所有选项(子命令)和用法、查看子命令的用法

$ docker --help
# 查看 attach 子命令的用法
$ docker attach --help

简单使用

常用的命令使用方式示例以及一些解释

hello world

镜像好比类, 容器好比实例, 镜像被run就形成了容器, 运行容器可以通过docker run命令

先来个简单例子:

$ docker run hello-world

当运行镜像hello-world时, 会先检查本地是否有这个镜像, 没有则会去仓库(默认是docker hub)下载

其他例子:

$ docker run ubuntu /bin/echo 'Hello world'
Hello world

交互式运行

$ docker run -t -i ubuntu /bin/bash
root@a98895ac1616:/#
  • -t flag: 给容器分配一个tty终端
  • -i flag: 可通过STDIN与容器交互
  • /bin/bash: 在容器里运行的bash shell, 可用shell命令exit退出容器

后台运行

$ docker run -d ubuntu /bin/sh -c "while true; do echo hello world; sleep 1; done"
28f3adccbae408573bbe6ecc03ad621d4257fbf1a79c672cc8d83ad327266807
  • -d flag: 后台运行容器(daemonize)
  • 输出的那一长串是container ID

查看容器

$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
28f3adccbae4        ubuntu              "/bin/sh -c 'while tr"   4 minutes ago       Up 4 minutes                            zen_curran
  • container ID: 前面那一长串的缩写
  • NAMES: 自动给容器起的名字, 每个容器的名字都是不一样的 另外:

  • docker ps: 仅查看运行中的容器
  • docker ps -l: 查看最后一次运行的容器(last)
  • docker ps -a: 查看所有运行过的容器

容器命名

$ docker run --name hello ubuntu /bin/echo 'Hello world'
Hello world
$ docker ps -l
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                     PORTS               NAMES
c4c79c82eb6c        ubuntu              "/bin/echo 'Hello wor"   48 minutes ago      Exited (0) 2 seconds ago                       hello
  • 容器的名字已经变成了hello而不再是自动起的名

查看容器的输出

$ docker logs zen_curran
hello world
hello world
...

停止/启动容器

$ docker stop zen_curran

可以再次运行某个容器

$ docker start zen_curran

删除容器

$ docker rm zen_curran

运行web程序(使用端口)

新下载一个镜像training/webapp, 运行python app.py可运行python写的web程序, 通过下面的命令运行容器

$ docker run -d -P training/webapp python app.py

查看该容器的信息:

$ docker ps -l
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                     NAMES
9b32553a8272        training/webapp     "python app.py"     12 minutes ago      Up 12 minutes       0.0.0.0:32768->5000/tcp   admiring_mayer

其中有个与其他程序不一样的地方:

PORTS
0.0.0.0:32768->5000/tcp

这就是-P的作用, 上面描述的意思是Dcoker容器里的端口是5000(Python Flask的默认端口)暴露到了属主机的32768端口.
上面-P的作用等同于-p 5000, 将暴露容器中的端口5000到一个更大的宿主机端口上(临时端口映射范围一般为32768~61000).
也可以自己指定使用某个具体的端口:

$ docker run -d -p 80:5000 training/webapp python app.py

访问容器运行起来的web程序地址为:127.0.0.1:80

查看端口

上面的docker ps可以看到容器的端口信息, 还有个更简单的命令docker port, 指定要查看的容器的nameID即可:

$ docker port 9b32553a8272
5000/tcp -> 0.0.0.0:32768
$ docker port admiring_mayer 5000
0.0.0.0:32768

查看程序日志

$ docker logs -f admiring_mayer
 * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
172.17.0.1 - - [19/Jul/2016 09:10:49] "GET / HTTP/1.1" 200 -
172.17.0.1 - - [19/Jul/2016 09:10:49] "GET /favicon.ico HTTP/1.1" 404 -
  • -f: 类似与tail -f的形式查看

检查容器

使用docker inspect命令可以获取一些信息, 如:

$ docker inspect admiring_mayer

可以看到一些json格式的信息:

[
    {
        "Id": "9b32553a82729a012b33b157abefb7639f1a59007042454f7ea543982a888466",
        "Created": "2016-07-19T08:40:01.882402323Z",
        "Path": "python",
        "Args": [
            "app.py"
        ],
        "State": {
            "Status": "running",
            "Running": true,
...

镜像操作

显示本地镜像

$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
ubuntu              latest              cf62323fa025        11 days ago         125 MB
hello-world         latest              c54a2cc56cbb        2 weeks ago         1.848 kB
  • REPOSITORY: 镜像来自哪个仓库, 如ubuntu
  • TAG: 镜像的版本, 如14.04, latest表示最新版本
  • IMAGE ID: 镜像的id

每个镜像都有很多版本, 你可以指定某个版本, 如$ docker run -t -i ubuntu:14.04 /bin/bash, 当不指定时, 默认都是latest.

获取镜像

之前都是直接run的, 会自动获取镜像, 也可以仅获取, 不运行:

$ docker pull ubuntu:14.04
$ docker pull centos

搜索镜像

可以去Docker Hub搜索镜像, 也可以在命令行搜索

$ docker search ubuntu
NAME                              DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
ubuntu                            Ubuntu is a Debian-based Linux operating s...   4293      [OK]       
ubuntu-upstart                    Upstart is an event-based replacement for ...   65        [OK]       
rastasheep/ubuntu-sshd            Dockerized SSH service, built on top of of...   29                   [OK]
  • STARS: 表示该镜像的受欢迎程度
  • OFFICIAL: 表示是官方制作的镜像
  • AUTOMATED: 表示是用户制作的镜像,/前面就是用户名

制作镜像

我们可以通过两种方式来制作镜像

  1. 可以更新镜像运行起来的容器, 在运行的容器中做修改, 然后提交这个修改得到新的镜像
  2. 可以写Dockerfile来指定具体如何创建某个镜像.

先来看看第一种方法.

通过training/sinatra镜像运行起来一个容器:

$ docker run -t -i training/sinatra /bin/bash
root@0b2616b0e5a8:/#

记住这个容器的id:0b2616b0e5a8,一会儿会用. 然后通过bash在容器中安装json gem

root@0b2616b0e5a8:/# gem install json

完成之后退出容器就可以了

最后我们用docker commit命令, 把刚才已经改变了的容器提交一个副本制作成镜像

$ docker commit -m "Added json gem" -a "Kate Smith" 0b2616b0e5a8 ouruser/sinatra:v2
4f177bd27a9ff0f6dc2a830403925b5360bfe0b93d476f7fc3231110e7f71b1c
  • -m: 添加描述信息, 类似于git commit -m
  • -a: 作者信息
  • 0b2616b0e5a8: 要制作成镜像的拿个容器的id
  • ouruser/sinatra:v2: 目标镜像, 用户为ouruser, 镜像名为sinatra, 版本(tag)为v2

第一种方法比较麻烦而且不利于团队间的合作分享, 下面看看第二种方法:

通过docker build命令编译Dockerfile来制作镜像, 首先创建一个目录和一个Dockerfile文件:

$ mkdir sinatra
$ cd sinatra
$ touch Dockerfile

然后在Dockerfile文件里添加类似于下面的内容:

# This is a comment
FROM ubuntu:14.04
MAINTAINER Kate Smith <ksmith@example.com>
RUN apt-get update && apt-get install -y ruby ruby-dev
RUN gem install sinatra

上面#开头的是注释, 下面是指令, 指令的格式类似于INSTRUCTION statement, 每条指令都会创建镜像的一层

  • FROM: 告诉Docker源镜像, 即我们是基于哪个镜像进行修改的
  • MAINTAINER: 用来说明是谁维护的这个镜像
  • RUN: 要在源镜像上做那些修改

最后我们编译Dockerfile

$ docker build -t ouruser/sinatra:v2 .
  • -t: 来指定一个新的tag, 形式为:name:tag
  • .: 注意后面有个., 用来表示编译当前目录里的Dockerfile文件, 也可以自己指定Dockerfile文件的位置

镜像的tag

我们可以给已经存在的镜像添加新的tag

docker tag ubuntu:14.04 rgkjhshi/ubuntu:newtag
docker tag b2f1fdd93175 rgkjhshi/ubuntu:newtag2

提交镜像

$ docker push rgkjhshi/ubuntu:newtag
# 提交所有tag
$ docker push rgkjhshi/ubuntu

删除镜像

$ docker rmi rgkjhshi/ubuntu:newtag2
# 不写tag 默认删除 latest
$ docker rmi rgkjhshi/ubuntu

Image Digests

v2或之后的格式的镜像, 有个唯一标识符叫做digest, 如果用于生成镜像的输入没有变,则digest值也是一样的

$ docker images --digests
REPOSITORY          TAG                 DIGEST                                                                    IMAGE ID            CREATED             SIZE
rgkjhshi/ubuntu     newtag              sha256:8d0f6d13291273ad6271c3c55b222ad08e28ff71a40c27487c79dbe80cce184f   b2f1fdd93175        40 hours ago        188.4 MB
rgkjhshi/ubuntu     newtag2             sha256:8d0f6d13291273ad6271c3c55b222ad08e28ff71a40c27487c79dbe80cce184f   b2f1fdd93175        40 hours ago        188.4 MB
ubuntu              14.04               sha256:b2c8a4d46473ab082200880391ddf8c06f2a67da4fa905ce2747dcd95d8d7af7   b2f1fdd93175        40 hours ago        188.4 MB
ubuntu              latest              sha256:ba1688fec34f66d8a7ff5b42e6971625d8232c72bf0e38ad06dda10cad157293   cf62323fa025        11 days ago         125 MB

2.0的仓库使用pushpull命令时都会显示镜像的digest, 我们也可以直接像这样使用digest:

$ docker pull rgkjhshi/ubuntu@sha256:8d0f6d13291273ad6271c3c55b222ad08e28ff71a40c27487c79dbe80cce184f
  • 若同一个digest有不同的tag, 则pull下来的镜像没有tag(显示的是<none>)
  • create, run, rmi命令甚至Dockerfile中的FROM都可以使用digest.