Docker 快速入门

Docker 快速入门

安装启动 Docker

yum install docker
systemctl start docker

这里我们使用 yum 安装 CentOS 自带源中的 Docker, 这个版本没有 Docker 自己的 yum 源中 Docker 版本高, 如果要安装最新的 Docker 版本,需要使用 Docker 自己的 yum 源安装。


# Docker 启动后,我们可以看到 Docker 启动了一个 docker0 网卡

[root@linux-node1 ~]# ifconfig
docker0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        inet 172.17.0.1  netmask 255.255.0.0  broadcast 0.0.0.0
        ether 02:42:93:3f:73:33  txqueuelen 0  (Ethernet)
        RX packets 2141  bytes 101161 (98.7 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 2318  bytes 13797412 (13.1 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

Docker 镜像管理

  • 搜索镜像:docker search
  • 获取镜像:docker pull
  • 查看镜像:docker images
  • 删除镜像:docker rmi

# 搜索 DockerHub 上的 centos/nginx 镜像,加星数至少为 10

[root@linux-node1 ~]# docker search -s 10 centos 
INDEX       NAME                                      DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
docker.io   docker.io/centos                          The official build of CentOS.                   2645      [OK]       
docker.io   docker.io/ansible/centos7-ansible         Ansible on Centos7                              85                   [OK]
docker.io   docker.io/jdeathe/centos-ssh              CentOS-6 6.8 x86_64 / CentOS-7 7.2.1511 x8...   33                   [OK]
docker.io   docker.io/jdeathe/centos-ssh-apache-php   CentOS-6 6.8 x86_64 / Apache / PHP / PHP M...   19                   [OK]
docker.io   docker.io/nimmis/java-centos              This is docker images of CentOS 7 with dif...   15                   [OK]
docker.io   docker.io/million12/centos-supervisor     Base CentOS-7 with supervisord launcher, h...   12                   [OK]
[root@linux-node1 ~]# docker search -s 10 nginx
INDEX       NAME                                DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
docker.io   docker.io/nginx                     Official build of Nginx.                        4117      [OK]       
docker.io   docker.io/jwilder/nginx-proxy       Automated Nginx reverse proxy for docker c...   794                  [OK]
docker.io   docker.io/richarvey/nginx-php-fpm   Container running Nginx + PHP-FPM capable ...   270                  [OK]
docker.io   docker.io/million12/nginx-php       Nginx + PHP-FPM 5.5, 5.6, 7.0 (NG), CentOS...   76                   [OK]
docker.io   docker.io/maxexcloo/nginx-php       Framework container with nginx and PHP-FPM...   58                   [OK]
docker.io   docker.io/webdevops/php-nginx       Nginx with PHP-FPM                              49                   [OK]
docker.io   docker.io/h3nrik/nginx-ldap         NGINX web server with LDAP/AD, SSL and pro...   29                   [OK]
docker.io   docker.io/bitnami/nginx             Bitnami nginx Docker Image                      18                   [OK]

# 查看本地镜像

[root@linux-node1 ~]# docker images
REPOSITORY                  TAG                 IMAGE ID            CREATED             SIZE

# 机器上没有 Docker 镜像,下面使用 docker pull 获取 nginx/centos 镜像

[root@linux-node1 ~]# docker pull nginx
Using default tag: latest
Trying to pull repository docker.io/library/nginx ... 
latest: Pulling from docker.io/library/nginx
8ad8b3f87b37: Pull complete 
c6b290308f88: Pull complete 
f8f1e94eb9a9: Pull complete 
Digest: sha256:aa5ac743d65e434c06fff5ceaab6f35cc8519d80a5b6767ed3bdb330f47e4c31
Status: Downloaded newer image for docker.io/nginx:latest
[root@linux-node1 ~]# docker pull centos
Using default tag: latest
Trying to pull repository docker.io/library/centos ... 
latest: Pulling from docker.io/library/centos
Digest: sha256:2ae0d2c881c7123870114fb9cc7afabd1e31f9888dac8286884f6cf59373ed9b
Status: Image is up to date for docker.io/centos:latest

# 查看刚才下载的镜像
[root@linux-node1 ~]# docker images
REPOSITORY                  TAG                 IMAGE ID            CREATED                  SIZE
docker.io/nginx             latest              4a88d06e26f4        Less than a second ago   183.5 MB
docker.io/centos            latest              980e0e4c79ec        5 days ago               196.7 MB


# 使用 docker save 将 centos 镜像保存成一个 tar 文件

[root@linux-node1 ~]# docker images
REPOSITORY                  TAG                 IMAGE ID            CREATED             SIZE
docker.io/centos            latest              980e0e4c79ec        5 days ago          196.7 MB
[root@linux-node1 ~]# docker save -o centos.tar centos
[root@linux-node1 ~]# ll centos.tar 
-rw-r--r-- 1 root root 204316160 Sep 12 19:43 centos.tar


# 使用 docker rmi 删除 centos 镜像

[root@linux-node1 ~]# docker images
REPOSITORY                  TAG                 IMAGE ID            CREATED             SIZE
docker.io/centos            latest              980e0e4c79ec        5 days ago          196.7 MB
[root@linux-node1 ~]# docker rmi 980e0e4c79ec
Untagged: docker.io/centos:latest
Deleted: sha256:980e0e4c79ec933406e467a296ce3b86685e6b42eed2f873745e6a91d718e37a
Deleted: sha256:0aeb287b1ba9fd4c951bb9f4bd8e50908f51c630e07b655b3b2f9581dc0fef0d

# 使用 docker load 将之前导出的镜像文件 centos.tar 再导入

[root@linux-node1 ~]# docker load --input centos.tar 
[root@linux-node1 ~]# docker images
REPOSITORY                  TAG                 IMAGE ID            CREATED                  SIZE
docker.io/nginx             latest              4a88d06e26f4        Less than a second ago   183.5 MB
docker.io/centos            latest              980e0e4c79ec        5 days ago               196.7 MB

Docker 容器管理

  • 运行容器:docker run
  • 停止容器:docker stop
  • 查看容器:docker ps
  • 进入容器:docker attach / nsenter / docker exec
  • 删除容器:docker rm

运行、停止、查看容器


# 运行一个 centos 窗口输出 “Hello world”

[root@linux-node1 ~]# docker run centos /bin/echo "Hello world"
Hello world

# 使用 docker ps -l 查看最新创建的一个容器
[root@linux-node1 ~]# docker ps -l
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                     PORTS               NAMES
9356550c0514        centos              "/bin/echo 'Hello wor"   5 minutes ago       Exited (0) 5 minutes ago                       stupefied_carson
# 从上面可以看到,容器状态为退出状态,说明上面的容器运行完成后就退出了

# 下面运行容器时指定名称,并使用 -t -i 开启伪终端和交互式 Shell,这样可以进入容器

[root@linux-node1 ~]# docker run --name mydocker -t -i centos /bin/bash
[root@68c901ac8f8a /]# ls /
anaconda-post.log  bin  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
[root@68c901ac8f8a /]# uname -a
Linux 68c901ac8f8a 3.10.0-327.18.2.el7.x86_64 #1 SMP Thu May 12 11:03:55 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
[root@68c901ac8f8a /]# ps aux
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.3  0.0  11752  1872 ?        Ss   08:55   0:00 /bin/bash
root        16  0.0  0.0  47424  1660 ?        R+   08:55   0:00 ps aux
[root@68c901ac8f8a /]# exit
exit

# 上面执行exit 就退出了容器,同时这个容器也退出了

[root@linux-node1 ~]# docker ps -l
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                     PORTS               NAMES
68c901ac8f8a        centos              "/bin/bash"         2 minutes ago       Exited (0) 8 seconds ago                       mydocker

# 执行 start 启动上面退出的容器

[root@linux-node1 ~]# docker start mydocker
mydocker

# 使用 docker ps 查看运行中的容器

[root@linux-node1 ~]# docker ps 
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
68c901ac8f8a        centos              "/bin/bash"         7 minutes ago       Up 13 seconds                           mydocker

进入容器

进入容器有三种方式:

  • 使用 docker attatch
  • 使用 nsenter
  • 使用 docker exec

1. 使用 docker attach 进入容器


[root@linux-node1 ~]# docker attach mydocker
[root@68c901ac8f8a /]# ps aux 
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.0  11776  1864 ?        Ss   09:02   0:00 /bin/bash
root        14  0.0  0.0  47424  1660 ?        R+   09:07   0:00 ps aux

# 此种方式有个不足:当多个终端都进入容器后,执行的操作会同步显示,当某个窗口因命令阻塞时,其他窗口也无法执行操作了。
# docker attach 进入容器后,执行 exit 容器也会 exit

2. 使用 nsenter 进入容器

nsenter 工具在 util-linux 包 2.23 版本后包含。
nsenter 可以访问另一个进程的命名空间。nsenter 要正常工作需要有 root 权限。


# 为了连接到容器,你还需要找到容器的第一个进程的 PID,可以通过下面的命令获取

[root@linux-node1 ~]# docker inspect -f "" mydocker
42667

# 通过这个 PID,就可以连接到这个容器

[root@linux-node1 ~]# nsenter -t 42667 -m -u -i -n -p
[root@68c901ac8f8a /]# ps aux
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.0  11776  1668 ?        Ss+  09:16   0:00 /bin/bash
root        14  0.2  0.1  13376  1984 ?        S    09:18   0:00 -bash
root        27  0.0  0.0  49024  1808 ?        R+   09:18   0:00 ps aux

# 我们可以看到有 2 个 bash,第二个 bash 是 nsenter 进入时执行的,当 exit 后,容器并不会退出

[root@68c901ac8f8a /]# exit
logout
[root@linux-node1 ~]# docker ps 
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
68c901ac8f8a        centos              "/bin/bash"         24 minutes ago      Up 4 minutes                            mydocker

我们可以将上面命令写成一个简单的进入 Docker 容器的脚本,如下:


root@linux-node1 ~]# vim docker_in.sh
[root@linux-node1 ~]# cat docker_in.sh
#!/bin/bash
# Use nsenter to enter docker

docker_in(){
   NAME_ID=$1
   PID=$(docker inspect -f "" $NAME_ID) 
   nsenter -t $PID -m -u -i -n -p
}

docker_in $1

[root@linux-node1 ~]# chmod +x docker_in.sh 
[root@linux-node1 ~]# ./docker_in.sh mydocker
[root@68c901ac8f8a /]# w
 09:23:03 up 10:22,  0 users,  load average: 0.00, 0.01, 0.05
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
[root@68c901ac8f8a /]# exit
logout

3. 使用 docker exec 进入容器


# docker exec 是在一个运行中的容器中运行一个命令,但是不进到容器里面,直接在容器外执行容器内的命令,如下:

[root@linux-node1 ~]# docker exec mydocker w
 09:35:08 up 10:34,  0 users,  load average: 0.00, 0.01, 0.05
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT

# 但我们可以使用以下技巧,执行 /bin/bash 达到进入容器的目的

[root@linux-node1 ~]# docker exec -it mydocker /bin/bash
[root@68c901ac8f8a /]# ps aux
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.0  11776  1668 ?        Ss+  09:16   0:00 /bin/bash
root        50  1.2  0.1  11776  1880 ?        Ss   09:36   0:00 /bin/bash
root        62  0.0  0.0  47424  1660 ?        R+   09:36   0:00 ps aux

# 注意:docker exec 方式可能会出现一些未知问题

对比上面 3 种进入容器的方式,建议使用 nsenter 的方式进入容器。

删除容器


# 使用 docker rm 删除容器

[root@linux-node1 ~]# docker rm mydocker
Failed to remove container (mydocker): Error response from daemon: Conflict, You cannot remove a running container. Stop the container before attempting removal or use -f
# 提示正在运行中的容器不能删除,可以使用 -f 参数强制删除,也可以 docker stop 停止容器后再删除

# 使用--rm,当容器运行完后就被删除,常用于测试目的

[root@linux-node1 ~]# docker run --rm centos /bin/echo "test"
test

守护态运行容器

更多的时候,需要让 Docker 在后台运行而不是直接把执行命令的结果输出在当前宿主机下。此时,可以通过添加 -d 参数来实现。


# 如果不使用 -d 参数运行容器

[root@linux-node1 ~]# docker run centos /bin/bash -c "while true; do echo hello world; sleep 1; done"
hello world
hello world
hello world
hello world
hello world
# 容器会把输出的结果(STDOUT)打印到宿主机上面

# 如果使用了 -d 参数运行容器

[root@linux-node1 ~]# docker run -d centos /bin/bash -c "while true; do echo hello world; sleep 1; done"
c303ceb3639b21564b82f09f006fff5eed1f842a7baa273b2314b9543c7e7c30

# 此时容器会在后台运行并不会把输出的结果(STDOUT)打印到宿主机上面(输出结果可以用 docker logs 查看)。

[root@linux-node1 ~]# docker logs c303ceb3639b
hello world
hello world
hello world
hello world
hello world
hello world
hello world
...

注: 容器是否会长久运行,是和 docker run 指定的命令有关,和 -d 参数无关。

Ref

Installation on CentOS
进入容器
后台(background)运行