Docker 使用

Docker 是一个开源的应用容器引擎, 基于 Go 语言 并遵从 Apache2.0 协议开源.

Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级, 可移植的容器中, 然后发布到任何流行的 Linux 机器上, 也可以实现虚拟化.

容器是完全使用沙箱机制, 相互之间不会有任何接口(类似 iPhone 的 app), 更重要的是容器性能开销极低.

安装

Linux

  1. 卸载旧版本

    1
    2
    3
    4
    5
    6
    7
    8
    $ sudo yum remove docker \
    docker-client \
    docker-client-latest \
    docker-common \
    docker-latest \
    docker-latest-logrotate \
    docker-logrotate \
    docker-engine
  2. 安装依赖

    1
    2
    3
    $ sudo yum install -y yum-utils \
    device-mapper-persistent-data \
    lvm2
  3. 设置仓库

    1
    2
    3
    $ sudo yum-config-manager \
    --add-repo \
    https://download.docker.com/linux/centos/docker-ce.repo
  4. 安装 Docker Engine-Community

    1
    $ sudo yum install docker-ce docker-ce-cli containerd.io

    默认安装的 docker-ce 是最新版, 如果想要安装其他版本的话可以:

    1. 先使用 yum list docker-ce --showduplicates | sort -r 命令找出所有可用版本
    2. 然后使用 sudo yum install docker-ce-<VERSION_STRING> docker-ce-cli-<VERSION_STRING> containerd.io 安装具体版本
  5. 启动 Docker

    1
    sudo systemctl start docker
  6. 运行 hello-world 来验证是否正确安装了 Docker Engine-Community

    1
    sudo docker run hello-world

MacOS

1
brew cask install docker

命令使用

  • docker network: 管理 docker 网络
  • docker image: 管理 docker 镜像
  • docker container: 管理 docker 容器

  • docker login: 登录 docker 账户, 需在 Hub Docker 提前注册账户, 登录后能拉取账号下的所有镜像

  • docker logout:: 退出登录

  • docker run <id/name>: 运行一个镜像

    1
    2
    docker run -i -t ubuntu:15.10 /bin/bash # 进入 ubuntun 的 15.10 版本镜像(需提前 pull), 并指定 shell 为 /bin/bash, 并进入交互模式
    docker run -itd --name ubuntu-hanley ubuntu:15.10 /bin/bash # 以后台, 终端, 交互式方式运行 ubuntu 这个镜像的 15.10 版本, 并将其命名为 ubuntu-hanley
  • exit: 在既然怒容器后的环境中执行, 退出一个容器

  • docker stop <id/name>: 停止一个正在运行的容器

  • docker start <id/name>: 启动一个已停止的容器

  • docker restart <id/name>: 重启一个容器

  • docker kill <id/name>:

  • docker ps: 查看当前正在运行的容器, 如果需要列出所有的(含已经被 exit 的)容器需要使用

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    $ docker ps

    CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
    31e46c0aad34 ubuntu "/bin/bash" 2 hours ago Up 2 hours test1
    2e8a12599649 training/webapp "python app.py" 2 hours ago Up 2 hours 127.0.0.1:5001->5000/tcp kind_bassi

    $ docker ps -a

    CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
    31e46c0aad34 ubuntu "/bin/bash" 2 hours ago Up 2 hours test1
    2e8a12599649 training/webapp "python app.py" 2 hours ago Up 2 hours 127.0.0.1:5001->5000/tcp kind_bassi
    62b13f6c9b2f training/webapp "python app.py" 2 hours ago Exited (137) 2 hours ago keen_jackson

    $ docker ps -l

    CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
    31e46c0aad34 ubuntu "/bin/bash" 2 hours ago Up 2 hours test1

  • docker images: 列出所有的位于本地的镜像

  • docker attach <id/name>: 运行容器使用 -d 参数后会在后台运行, 使用 attach 可以进入此容器

  • docker exec: 与 attach 类似, 但是在此命令下使用 exit 并不会导致容器停止运行, 因此这种方式更好.

    1
    docker exec -it
  • docker rm <id/name>: 删除某个容器, docker rm -f 1e560fca3906

  • docker container prune: 删除所有不在运行的容器

  • docker rmi <image name>: 删除某个镜像

  • docker port <id/name>: 查看某个容器的映射端口详情

    1
    2
    3
    4
    5
    $ docker port 1e560fca3906
    5000/tcp -> 0.0.0.0:5000

    $ docker port wizardly_chandrasekhar
    5000/tcp -> 0.0.0.0:5000
  • docker logs <id/name>: 查看某个容器的内部标准输出, -f 像使用 tail -f 一样来输出容器内部的标准输出

  • docker top <id/name>: 查看某个容器的内部运行的进程信息

    1
    2
    3
    $docker top 1e560fca3906
    UID PID PPID C STIME TTY TIME CMD
    root 14019 14002 0 May23 ? 00:00:01 python app.py
  • docker inspect <id/name>: 查看容器的底层信息, 会返回一个 json 文件记录 docker 容器的配置与状态信息

  • docker export <id/name> > <name>: 导出一个容器快照到本地, docker export 1e560fca3906 > ubuntu.tar

  • docker import: 从本地导入容器快照, cat docker/ubuntu.tar | docker import - test/ubuntu:v1, 另外也可以通过指定 URL 或者某个目录来导入 docker import http://example.com/exampleimage.tgz example/imagerepo

  • docker commit -m="" -a "" <原有 id/name> <最新 name>: 更新镜像, docker commit -m="has update" -a="hanleylee" e218edb10161 hanleylee/ubuntu:v2

  • docker tag <id/name> <new name>: 为镜像添加一个新的标签, new name 格式为 用户名/镜像名:tag

    1
    2
    3
    4
    5
    6
    $ docker tag 860c279d2fec hanleylee/ubuntu:v3

    $ docker images
    REPOSITORY TAG IMAGE ID CREATED SIZE
    hanleylee/ubuntu 6.7 860c279d2fec 5 hours ago 190.6 MB
    hanleylee/ubuntu dev 860c279d2fec 5 hours ago 190.6 MB
  • docker rename

  • docker search <image name>: 根据 name 搜索一个镜像

  • docker pull <image name>: 从远程仓库载入镜像, docker pull ubuntu; 也可以指定版本: docker pull ubuntu:15.10

  • docker push <image name>: 推送本地创建或更新的镜像到远程自己的仓库中, docker push hanlyelee/ubuntu:18.04

  • docker history

  • -b:

  • -d: 在后台运行

  • -i: 进入交互式操作

  • -t: 终端

  • -P: 将容器内部使用的网络端口以随机方式映射到我们使用的主机上

    1
    2
    3
    4
    $ docker run -d -P training/webapp python app.py
    $ docker ps

    2a8df02af645 training/webapp "python app.py" 2 hours ago Up 2 hours 0.0.0.0:32768->5000/tcp hanley
  • -p: 将容器内部使用的网络端口指定映射到我们使用的主机上

    1
    2
    3
    4
    $ docker run -d -p 127.0.0.1:5001:5000 training/webapp python app.py
    $ docker ps

    2e8a12599649 training/webapp "python app.py" 2 hours ago Up 2 hours 127.0.0.1:5001->5000/tcp kind_bassi
  • --help: 使用帮助查看具体命令的使用, docker image --help

  • --name: 以现有镜像创建自定义名称的容器, docker run -itd --name test1 --network test-net ubuntu /bin/bash

  • --network: 以现有镜像创建使用自定义网络的容器

容器属性

使用 docker ps -a 可列出所有存在的容器

1
2
3
4
5
6
7
8
9
$ docker ps -a

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8e7f63c63e6b ubuntu "/bin/bash" 2 hours ago Up 2 hours test2
31e46c0aad34 ubuntu "/bin/bash" 2 hours ago Up 2 hours test1
2a8df02af645 training/webapp "python app.py" 2 hours ago Up 2 hours 0.0.0.0:32768->5000/tcp hanley
2e8a12599649 training/webapp "python app.py" 2 hours ago Up 2 hours 127.0.0.1:5001->5000/tcp kind_bassi
dc33b04b866b training/webapp "python app.py" 2 hours ago Created cranky_hawking
62b13f6c9b2f training/webapp "python app.py" 2 hours ago Exited (137) 2 hours ago keen_jackson

容器有以下属性:

  • CONTAINER ID: 容器 ID.
  • IMAGE: 使用的镜像.
  • COMMAND: 启动容器时运行的命令.
  • CREATED: 容器的创建时间.
  • STATUS: 容器状态.
    • created: 已创建
    • restarting: 重启中
    • running: 运行中
    • removing: 迁移中
    • paused: 暂停
    • exited: 停止
    • dead: 死亡
  • PORTS: 容器的端口信息和使用的连接类型(tcp\udp).
  • NAMES: 自动分配的容器名称.

镜像属性

使用 docker images 可列出所有存在的镜像

1
2
3
4
5
6
7
8
9
10
11
$ docker images

REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu 14.04 90d5884b1ee0 5 days ago 188 MB
php 5.6 f40e9e0f10c8 9 days ago 444.8 MB
nginx latest 6f8d099c3adc 12 days ago 182.7 MB
mysql 5.6 f2e8d6c772c0 3 weeks ago 324.6 MB
httpd latest 02ef73cf1bc0 3 weeks ago 194.4 MB
ubuntu 15.10 4e3b13c8a266 4 weeks ago 136.3 MB
hello-world latest 690ed74de00f 6 months ago 960 B
training/webapp latest 6fae60ef3446 11 months ago 348.8 MB

镜像有以下属性:

  • REPOSITORY: 表示镜像的仓库源

  • TAG: 镜像的标签

    在一个仓库源中, 可能有多个 tag, tag 不同则代表不同的版本, 表示不同的镜像, 哪怕两个镜像完全一致, 只有 tag 不一致, 那也是不同的镜像

  • IMAGE ID: 镜像ID

  • CREATED: 镜像创建时间

  • SIZE: 镜像大小

实际使用

更新镜像

1
2
3
4
5
6
7
8
9
10
11
12
13
$ docker run -t -i ubuntu:15.10 /bin/bash # 首先创建一个容器
root@e218edb10161 apt-get update # 更新此容器
root@e218edb10161 exit
$ docker commit -m="has update" -a="hanleylee" e218edb10161 hanleylee/ubuntu:v2 # 根据更新后的容器创建新镜像 hanleylee/ubuntu:v2
$ docker images

REPOSITORY TAG IMAGE ID CREATED SIZE
hanleylee/ubuntu v2 70bf1840fd7c 15 seconds ago 158.5 MB
ubuntu 15.10 4e3b13c8a266 4 weeks ago 136.3 MB
mysql 5.6 f2e8d6c772c0 3 weeks ago 324.6 MB
httpd latest 02ef73cf1bc0 3 weeks ago 194.4 MB
hello-world latest 690ed74de00f 6 months ago 960 B
training/webapp latest 6fae60ef3446 12 months ago 348.8 MB

容器互联

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$ docker run -d -P --name hanley training/webapp python app.py
$ docker ps -l
CONTAINER ID IMAGE COMMAND ... PORTS NAMES
43780a6eabaa training/webapp "python app.py" ... 0.0.0.0:32769->5000/tcp hanley

$ docker network create -d bridge test-net # 创建网络, -d: 参数指定 Docker 网络类型, 有 bridge, overlay.
$ docker run -itd --name test1 --network test-net ubuntu /bin/bash # 运行一个容器并连接到新建的 test-net 网络
$ docker run -itd --name test2 --network test-net ubuntu /bin/bash # 打开新的终端, 再运行一个容器并加入到 test-net 网络

$ docker exec -it test1 /bin/bash
root@ed123dfvcxd: ping test2

64 bytes from test2. test-net ...... # 正确接收到来自 test2 的信息

root@ed123dfvcxd: exit

$ docker exec -it test2 /bin/bash
root@1sdaf124232: ping test1

64 bytes from test1. test-net ...... # 正确接收到来自 test1 的信息