Docker基础知识 (2) - Hello world、Docker 容器、Docker 镜像


1. Hello world

    Docker 在容器中运行应用程序,一般的开发语言教程,都有一个 Hello World 示例,我们的 Docker 容器介绍也从 Hello World 开始。

    1) Hello world 示例

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

            Hello world

        各个参数解析:

            docker: Docker 命令。
            run: Docker 命令下的 Action (动作或操作),表示运行一个容器。
            ubuntu:表示运行的镜像,Docker 首先从本地主机上查找镜像是否存在,如果不存在,Docker 就会从镜像仓库 Docker Hub 下载公共镜像。 默认情况下会下载 TAG 为 latest 的镜像,示例里是 Ubuntu 20.04.3 LTS。
            /bin/echo "Hello world": 在容器里执行 Linux 命令 /bin/echo

        以上命令完整的意思是:Docker 以 ubuntu 镜像创建一个新容器,然后在容器里执行 bin/echo "Hello world",然后输出结果。

        docker run 是创建一个容器并运行一个命令,如果要创建一个容器但不运行命令,可以使用 docker create。

        注:命令执行时,如需 root 权限的,切换到 root 或 root 组用户下运行,下同。

    2) 交互式容器

        通过 docker 的两个参数 -i -t,让 docker 运行的容器实现 "对话" 的能力:

            $ docker run -i -t ubuntu /bin/bash
        
            root@46ff069b5f64:/#
        
        各个参数解析:

            -t: 在新容器内指定一个伪终端或终端。
            -i: 允许你对容器内的标准输入 (STDIN) 进行交互。

        注意第二行 root@46ff069b5f64:/#,此时我们已进入一个 ubuntu 系统的容器

        在容器中运行命令 cat 和 ls 分别查看当前系统的版本信息和当前目录下的文件列表

            root@46ff069b5f64:/#cat /etc/issue

                Ubuntu 20.04.3 LTS \n \l

            root@46ff069b5f64:/#
        
                bin  boot  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
        
        可以通过运行 exit 命令或者使用 CTRL+D 来退出容器。

            root@46ff069b5f64:/#  exit
    
                exit

            [root@localhost /]#

        退出容器,返回到当前的主机中。

    3) 后台运行容器

        使用以下命令创建一个以进程方式运行的容器

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

                64b3215d2e86f3db9fda639acfbe4009815d182fe08614cd9051b7763d7b2a6a
        
        在输出中,没有看到期望的 "hello world",而是一串长字符 "64b3215d2e86 ... ",这个长字符串叫做容器 ID,对每个容器来说都是唯一的,我们可以通过容器 ID 来查看对应的容器发生了什么。

        使用 docker ps 查看运行的容器列表:

            $ docker ps

            CONTAINER ID  IMAGE          COMMAND        CREATED  STATUS    PORTS     NAMES
            64b3215d2e86  ubuntu          "/bin/s ..."              ...              ...             ...        brave_wozniak

            注:64 位的容器 ID 列表显示了前 12 位。可以使用 docker ps -a 命令查看全部容器列表,包含停止运行的容器。容器名称 brave_wozniak 是 docker 自动指定的。
            
        输出详情介绍:

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

        在宿主主机内使用 docker logs 命令,查看容器内的标准输出:

            $ docker logs 64b3215d2e86

    4) 进入容器

        使用 -d 参数时,容器启动后会进入后台。此时想要进入容器,可以通过以下指令进入:

            (1) docker attach
            (2) docker exec:推荐大家使用 docker exec 命令,因为此命令会退出容器终端,但不会导致容器的停止。

        attach 命令:

            $ docker attach 64b3215d2e86

            注:从这个容器退出,会导致容器的停止。

        exec 命令:

            $ docker exec -it 64b3215d2e86 /bin/bash

            注: 从这个容器退出,容器不会停止。更多参数说明请使用 docker exec --help 命令查看。

    5) 停止容器

        使用 docker stop "CONTAINER ID" 命令来停止容器:

            $ docker stop 639d4e201537

            639d4e201537

        也可以使用 docker stop "NAMES" 命令来停止容器:

            $ docker stop loving_hypatia


 2. Docker 容器

    上文通过 Hello world 示例,演示了 docker run 在容器里运行应用程序,同时使用了 ubuntu 镜像。也简单介绍了如何运行交互式容器、后台运行容器、进入后台运行的容器及停止容器。

    这里我们将通过一个 Web 应用示例,介绍一些 Docker 容器的其它操作和功能。

    1) Python Web 应用 (Flask)

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

            aeb5c373a4f70cf534540a1d9e21d2db0985fa0935a93199c32a4cb9703cfce6

        参数说明:

            -d: 让容器在后台运行。
            -P: 将容器内部使用的网络端口随机映射到主机上。
            --name: 指定容器名称为 webtest01。

        使用 docker ps 查看运行的容器列表:

            $ docker ps

            CONTAINER ID  IMAGE            ...         PORTS                           NAMES
            aeb5c373a4f7  training/webapp  ...   0.0.0.0:49157->5000/tcp    webtest01
            
        Docker 开放了 5000 端口(默认 Python Flask 端口)映射到主机端口 49157 上。

        浏览器访问 http://192.168.0.10:49157 (这个 IP 地址是在前文安装 CentOS 时,设置的静态 IP 地址),页面显示:

            Hello world!

    2) 设置指定端口
    
        通过 -p 参数来设置指定端口,注意是小写的 p,大写的 P 是随机映射端口。

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

        可以绑定 IP 地址,格式如下:

             $ docker run -d -p 192.168.0.10:5000:5000 --name webtest02 training/webapp python app.py

                3904176f769d618dda5fb3332fe39b2d60ebae46318de030784568e12eebe804

        使用 docker ps 查看运行的容器列表:

           $ docker ps

            CONTAINER ID  IMAGE            ...         PORTS                                  NAMES
            3904176f769d  training/webapp  ...   192.168.0.10:5000->5000/tcp     webtest02
            aeb5c373a4f7  training/webapp  ...   0.0.0.0:49157->5000/tcp           webtest01


       浏览器访问 http://192.168.0.10:5000 (这个 IP 地址是在前文安装 CentOS 时,设置的静态 IP 地址),页面显示:

            Hello world!

    3) 查看容器的端口映射

        使用 docker port [ID 或者名字] 可以查看容器的端口映射。

            $ docker port webtest01

                5000/tcp -> 0.0.0.0:49157
                5000/tcp -> :::49157

            $ docker port webtest02

                5000/tcp -> 127.0.0.1:5000

    4) 查看容器内的程序日志

        可以使用 docker logs [ID或者名字] 查看容器内部的标准输出。

            $ docker logs -f webtest02

            * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
            192.168.0.2 - - [07/Jul/2022 00:00:18] "GET / HTTP/1.1" 200 -
            192.168.0.2 - - [07/Jul/2022 00:00:20] "GET / HTTP/1.1" 200 -
            192.168.0.2 - - [07/Jul/2022 00:00:20] "GET / HTTP/1.1" 200 -
            192.168.0.2 - - [07/Jul/2022 00:00:21] "GET / HTTP/1.1" 200 -


            -f: 让 docker logs 像使用 tail -f 一样来输出容器内部的标准输出。

    5) 查看容器内的进程

        可以使用 docker top [ID或者名字] 查看容器内部运行的进程

        $ docker top webtest02

        UID      PID        PID     ...         TIME                CMD
        root    5589       5570     ...       00:00:00            python app.py

    6) 检查容器详细信息

        可以使用 docker inspect [ID或者名字] 查看容器详细信息,它会返回一个 JSON 格式的输出。

        $ docker inspect webtest02

            [
                {
                    "Id": "3904176f769d618dda5fb3332fe39b2d60ebae46318de030784568e12eebe804",
                    "Created": "2022-07-06T23:59:05.249257511Z",
                    "Path": "python",
                    "Args": [
                        "app.py"
                    ],

                ...
            ]

       
    7) 重启容器

        运行 docker stop webtest02,停止 webtest02。

        使用命令 docker start [ID或者名字] 启动已经停止的容器。

            $ docker start webtest02

                webtest02

        查询最后一次创建的容器:

            $ docker ps -l

            CONTAINER ID   IMAGE                    PORTS                                   NAMES
            3904176f769d   training/webapp  ...  192.168.0.10:5000->5000/tcp    webtest02

        正在运行的容器,可以使用 docker restart [ID或者名字] 命令来重启。

    8) 导出容器

        要导出本地某个容器,可以使用 docker export 命令。

            $ docker export webtest02 > webtest02_export.tar

        导出容器 webtest02 快照到本地文件 webtest02_export.tar 中。

    9) 导入容器快照

        可以使用 docker import 从容器快照文件中再导入为镜像,以下实例将快照文件 webtest02_export.tar 导入到镜像 training/webapp:v1:

            $ cat webtest02_export.tar | docker import - training/webapp:v1

        查看导入的容器快照:

            $ docker images

            REPOSITORY        TAG       IMAGE ID         CREATED            SIZE
            training/webapp     v1        36ed53a7958f   51 seconds ago   324MB
            ubuntu                 latest    9b9cb95443b5  8 months ago      72.8MB
            training/webapp    latest    6fae60ef3446   7 years ago         349MB   


            注:training/webapp:v1 已经在镜像列表里。     

        也可以通过指定 URL 或者某个目录来导入,例如:

            $ docker import http://example.com/webtest02_export.tar training/webapp:v1

    10) 移除容器

        可以使用 docker rm [ID或者名字] 命令来删除容器。

            $ docker rm webtest01

                webtest01

        删除容器时,容器必须是停止状态,否则会报如下错误。

            Error response from daemon: You cannot remove a running container aeb5c373a4f70cf534540a1d9e21d2db0985fa0935a93199c32a4. Stop the container before attempting removal or force remove

        下面的命令可以清理掉所有处于终止状态的容器。

            $ docker container prune


3. Docker 镜像

    当运行容器时,使用的镜像如果在本地中不存在,docker 就会自动从 docker 镜像仓库中下载,默认是从 Docker Hub 公共镜像源下载。

    1) 列出镜像列表

        可以使用 docker images 来列出本地主机上的镜像。

        $ docker images

            REPOSITORY        TAG       IMAGE ID        CREATED         SIZE
            ubuntu                 latest    ba6acccedd29   8 months ago   72.8MB
            hello-world           latest    feb5d9fea6a5   9 months ago    13.3kB
            training/webapp    latest    6fae60ef3446   7 years ago       349MB


        各项说明:

            REPOSITORY:表示镜像的仓库源
            TAG:镜像的标签
            IMAGE ID:镜像ID
            CREATED:镜像创建时间
            SIZE:镜像大小

        同一仓库源可以有多个 TAG,代表这个仓库源的不同个版本,如 ubuntu 仓库源里,有 15.10、14.04 等多个不同的版本,使用 REPOSITORY:TAG 来定义不同的镜像。

        如果要使用版本为 15.10 的 ubuntu 系统镜像来运行容器时,命令如下:

            $ docker run -t -i ubuntu:15.10 /bin/bash
            root@9b9cb95443b5:/#

        参数说明:

            -i: 交互式操作。
            -t: 终端。
            ubuntu:15.10: 这是指用 ubuntu 15.10 版本镜像为基础来启动容器。
            /bin/bash:放在镜像名后的是命令,这里我们希望有个交互式 Shell,因此用的是 /bin/bash。

        如果不指定一个镜像的版本标签,例如你只使用 ubuntu,docker 将默认使用 ubuntu:latest 镜像。

    2) 获取一个新的镜像

        当我们在本地主机上使用一个不存在的镜像时 Docker 就会自动下载这个镜像。如果我们想预先下载这个镜像,可以使用 docker pull 命令来下载,命令格式如下。

            $ docker pull ubuntu:15.10

                15.10: Pulling from library/ubuntu
                6599cadaf950: Pull complete
                23eda618d451: Pull complete
                f0be3084efe9: Pull complete
                52de432f084b: Pull complete
                a3ed95caeb02: Pull complete
                Digest: sha256:15b79a6654811c8d992ebacdfbd5152fcf3d165e374e264076aa435214a947a3
                Status: Downloaded newer image for ubuntu:15.10


        下载完成后,可以直接使用这个镜像来运行容器。

    3) 查找镜像

        可以从 Docker Hub 网站 ( https://hub.docker.com/ ) 搜索镜像。

        也可以使用 docker search 命令来搜索镜像。比如需要一个 httpd 的镜像来作为 web 服务。可以通过 docker search 命令搜索 httpd 来寻找适合的镜像,命令格式如下。

            $ docker search httpd

            NAME                                   DESCRIPTION                        STARS  OFFICIAL  AUTOMATED
            httpd                                The Apache HTTP Server Project      4070       [OK]
            centos/httpd-24-centos7   Platform for running Apache …         44
            centos/httpd                                                                          35                            [OK]
            hypoport/httpd-cgi             httpd-cgi                                       2                              [OK]
            solsson/httpd-openidc        mod_auth_openidc on official …        2                              [OK]

            ...


        各项说明:

            NAME: 镜像仓库源的名称
            DESCRIPTION: 镜像的描述
            STARS: 类似 Github 里面的 star,表示点赞、喜欢的意思。
            OFFICIAL: 是否 docker 官方发布
            AUTOMATED: 自动构建。

    4) 查看镜像详细信息

        可以使用 docker inspect [REPOSITORY:TAG] 查看镜像详细信息,它会返回一个 JSON 格式的输出。

            $ docker inspect ubuntu

                [
                    {
                        "Id": "sha256:9b9cb95443b5f846cd3c8cfa3f64e63b6ba68de2618a08875a119c81a8f96698",
                        "RepoTags": [
                            "ubuntu:latest"
                        ],
                        "RepoDigests": [
                            "ubuntu@sha256:02521a2d079595241c6793b2044f02eecf294034f31d6e235ac4b2b54ffc41f3"
                        ],

                    ...
                ]


    5) 查看镜像历史

        可以使用 docker history [REPOSITORY:TAG] 查看镜像历史。

        $ docker history ubuntu

        IMAGE                CREATED        CREATED BY                                                     SIZE
        ba6acccedd29   8 months ago   /bin/sh -c #(nop)  CMD ["bash"]                             0B
        <missing>         8 months ago   /bin/sh -c #(nop) ADD file:5d68d27cc15a80653…   72.8MB


    6) 更新镜像

        更新镜像之前,需要使用镜像来创建一个容器。

            $ docker run -t -i ubuntu /bin/bash
            root@a1c24a6cd008:/#

        在运行的容器内安装 ping 软件(本文 Ubuntu 的 latest 版本是 20.04.3 LTS),在完成操作之后,输入 exit 命令来退出这个容器。
        
            $ apt-get update
            $ apt install iputils-ping
            $ exit
      
        通过命令 docker commit 来提交更新过的容器副本,命令格式如下。

            $ docker commit -m="Install iputils-ping" -a="Tester" a1c24a6cd008 tester/ubuntu:20.04.ping

                sha256:927000729bfb64f7bda2fd5f249113b926e1647498a161bd1746d05b599567e4
        
            参数说明:

                -m: 提交的描述信息
                -a: 指定镜像作者
                a1c24a6cd008: 容器 ID
                tester/ubuntu:20.04.ping: 指定要创建的目标镜像名

        查看镜像列表:

            $ docker images

            REPOSITORY        TAG          IMAGE ID          CREATED                    SIZE
            tester/ubuntu     20.04.ping   927000729bfb   About a minute ago     95.4MB
            ubuntu                latest         ba6acccedd29   8 months ago             72.8MB
            hello-world          latest         feb5d9fea6a5    9 months ago             13.3kB
            training/webapp   latest         6fae60ef3446    7 years ago                349MB

           
        使用新镜像 tester/ubuntu 来启动一个容器

            $ docker run -t -i tester/ubuntu:20.04.ping /bin/bash                            

            root@0861e95c1a59:/# ping www.baidu.com

                PING www.a.shifen.com (36.152.44.95) 56(84) bytes of data.
                64 bytes from 36.152.44.95 (36.152.44.95): icmp_seq=1 ttl=55 time=16.1 ms
                64 bytes from 36.152.44.95 (36.152.44.95): icmp_seq=2 ttl=55 time=15.8 ms
                64 bytes from 36.152.44.95 (36.152.44.95): icmp_seq=3 ttl=55 time=15.4 ms


    7) 创建镜像

        使用命令 docker build,从零开始来创建一个新的镜像。需要创建一个 Dockerfile 文件,内容如下:

            FROM    centos:6.7
            MAINTAINER     Tester "tester@docker.com"

            RUN     /bin/echo 'root:123456' | chpasswd
            RUN     useradd develop
            RUN     /bin/echo 'develop:123456' | chpasswd
            RUN     /bin/echo -e "LANG=\"en_US.UTF-8\"" >/etc/default/local
            EXPOSE  22
            EXPOSE  80
            CMD     /usr/sbin/sshd -D


            说明:

                FROM:指定使用哪个镜像源
                RUN:指令告诉 docker 在镜像内执行命令

        使用 Dockerfile 文件,通过 docker build 命令来构建一个镜像,命令格式如下。

            $ docker build -t tester/centos:6.7 .

                Sending build context to Docker daemon  2.048kB
                Step 1/9 : FROM    centos:6.7
                6.7: Pulling from library/centos
                cbddbc0189a0: Pull complete
                Digest: sha256:4c952fc7d30ed134109c769387313ab864711d1bd8b4660017f9d27243622df1
                Status: Downloaded newer image for centos:6.7
                ---> 9f1de3c6ad53

                ...

                Step 9/9 : CMD     /usr/sbin/sshd -D
                ---> Running in 4d67b1f3f0c6
                Removing intermediate container 4d67b1f3f0c6
                ---> f5bff2907032
                Successfully built f5bff2907032
                Successfully tagged tester/centos:6.7


            参数说明:

                -t :指定要创建的目标镜像名
                . :Dockerfile 文件所在目录,可以指定 Dockerfile 的绝对路径

        查看镜像列表:

            $ docker images

            REPOSITORY        TAG       IMAGE ID       CREATED                SIZE
            tester/centos       6.7       f5bff2907032    About a minute ago   191MB
            tester/ubuntu       v2        48c392bf562a   8 minutes ago          137MB
            ubuntu               latest     ba6acccedd29   8 months ago           72.8MB
            centos                 6.7       9f1de3c6ad53   3 years ago              191MB
            training/webapp   latest    6fae60ef3446   7 years ago              349MB


        使用新的镜像来创建容器:

            $ docker run -t -i tester/centos:6.7  /bin/bash
            [root@1eb692acaefd /]# id develop

                uid=500(develop) gid=500(develop) groups=500(develop)

        可以看到新镜像已经包含新创建的用户 develop。

    8) 设置镜像标签

        可以使用 docker tag 命令,为镜像添加一个新的标签,命令格式如下。

            $ docker tag f5bff2907032 tester/centos:dev

            参数说明:

                f5bff2907032:镜像ID
                tester/centos:dev:用户名称/镜像源名(repository name):标签名(tag)

        查看镜像列表:

            $ docker images

                REPOSITORY        TAG       IMAGE ID       CREATED              SIZE
                tester/centos       6.7       f5bff2907032    12 minutes ago       191MB
                tester/centos       dev       f5bff2907032    12 minutes ago      191MB
                tester/ubuntu       v2        48c392bf562a   20 minutes ago     137MB
                ubuntu                latest    ba6acccedd29   8 months ago        72.8MB
                centos                 6.7       9f1de3c6ad53    3 years ago           191MB
                training/webapp   latest    6fae60ef3446    7 years ago           349MB


            IMAGE ID 为 f5bff2907032 的镜像多一个标签 dev。

    9)删除镜像

        使用 docker rmi [名称:tag] 命令删除镜像,命令格式如下。

        $ docker rmi hello-world

            Untagged: hello-world:latest
            Untagged: hello-world@sha256:13e367d31ae85359f42d637adf6da428f76d75dc9afeb3c21faea0d976f5c651
            Deleted: sha256:feb5d9fea6a5e9606aa995e879d862b825965ba48de054caab5ef356dc6b3412
            Deleted: sha256:e07ee1baac5fae6a26f30cabfe54a36d3402f96afda318fe0a96cec4ca393359



posted @ 2022-07-11 09:13  垄山小站  阅读(1114)  评论(0)    收藏  举报