精华内容
下载资源
问答
  • docker详细教程

    2016-10-19 09:07:54
    7、Docker常用命令讲解 docker version #查看版本 docker search centos#搜索可用docker镜像 docker images 查看当前...docker pull centos #下载镜像 cat centos.tar | docker import - centos6 #Docker导入镜像...
  • Docker详细教程

    2018-10-20 10:20:33
    Docker: 开源的容器虚拟化平台 Docker Hub: 用于分享、管理 Docker 容器的 Docker SaaS 平台 -- Docker Hub Docker 使用客户端-服务器 (C/S) 架构模式。Docker 客户端会与 Docker 守护进程进行通信。Docker 守护...

    一、Docker 简介

    Docker 两个主要部件:

    • Docker: 开源的容器虚拟化平台
    • Docker Hub: 用于分享、管理 Docker 容器的 Docker SaaS 平台 -- Docker Hub

    Docker 使用客户端-服务器 (C/S) 架构模式。Docker 客户端会与 Docker 守护进程进行通信。Docker 守护进程会处理复杂繁重的任务,例如建立、运行、发布你的 Docker 容器。Docker 客户端和守护进程可以运行在同一个系统上,当然你也可以使用 Docker 客户端去连接一个远程的 Docker 守护进程。Docker 客户端和守护进程之间通过 socket 或者 RESTful API 进行通信。

    非常详细的 Docker 学习笔记

    1.1 Docker 守护进程

    如上图所示,Docker 守护进程运行在一台主机上。用户并不直接和守护进程进行交互,而是通过 Docker 客户端间接和其通信。

    1.2 Docker 客户端

    Docker 客户端,实际上是 docker 的二进制程序,是主要的用户与 Docker 交互方式。它接收用户指令并且与背后的 Docker 守护进程通信,如此来回往复。

    1.3 Docker 内部

    要理解 Docker 内部构建,需要理解以下三种部件:

    • Docker 镜像 - Docker images
    • Docker 仓库 - Docker registeries
    • Docker 容器 - Docker containers

    Docker 镜像

    Docker 镜像是 Docker 容器运行时的只读模板,每一个镜像由一系列的层 (layers) 组成。Docker 使用 UnionFS 来将这些层联合到单独的镜像中。UnionFS 允许独立文件系统中的文件和文件夹(称之为分支)被透明覆盖,形成一个单独连贯的文件系统。正因为有了这些层的存在,Docker 是如此的轻量。当你改变了一个 Docker 镜像,比如升级到某个程序到新的版本,一个新的层会被创建。因此,不用替换整个原先的镜像或者重新建立(在使用虚拟机的时候你可能会这么做),只是一个新 的层被添加或升级了。现在你不用重新发布整个镜像,只需要升级,层使得分发 Docker 镜像变得简单和快速。

    Docker 仓库

    Docker 仓库用来保存镜像,可以理解为代码控制中的代码仓库。同样的,Docker 仓库也有公有和私有的概念。公有的 Docker 仓库名字是 Docker Hub。Docker Hub 提供了庞大的镜像集合供使用。这些镜像可以是自己创建,或者在别人的镜像基础上创建。Docker 仓库是 Docker 的分发部分。

    Docker 容器

    Docker 容器和文件夹很类似,一个Docker容器包含了所有的某个应用运行所需要的环境。每一个 Docker 容器都是从 Docker 镜像创建的。Docker 容器可以运行、开始、停止、移动和删除。每一个 Docker 容器都是独立和安全的应用平台,Docker 容器是 Docker 的运行部分。

    1.4 libcontainer

    Docker 从 0.9 版本开始使用 libcontainer 替代 lxc,libcontainer 和 Linux 系统的交互图如下:

    非常详细的 Docker 学习笔记

    1.5 命名空间「Namespaces」

    pid namespace

    不同用户的进程就是通过 pid namespace 隔离开的,且不同 namespace 中可以有相同 PID。具有以下特征:

    • 每个 namespace 中的 pid 是有自己的 pid=1 的进程(类似 /sbin/init 进程)
    • 每个 namespace 中的进程只能影响自己的同一个 namespace 或子 namespace 中的进程
    • 因为 /proc 包含正在运行的进程,因此在 container 中的 pseudo-filesystem 的 /proc 目录只能看到自己 namespace 中的进程
    • 因为 namespace 允许嵌套,父 namespace 可以影响子 namespace 的进程,所以子 namespace 的进程可以在父 namespace 中看到,但是具有不同的 pid

    参考文档:Introduction to Linux namespaces – Part 3: PID

    mnt namespace

    类似 chroot,将一个进程放到一个特定的目录执行。mnt namespace 允许不同 namespace 的进程看到的文件结构不同,这样每个 namespace 中的进程所看到的文件目录就被隔离开了。同 chroot 不同,每个 namespace 中的 container 在 /proc/mounts 的信息只包含所在 namespace 的 mount point。

    net namespace

    网络隔离是通过 net namespace 实现的, 每个 net namespace 有独立的 network devices, IP addresses, IP routing tables, /proc/net 目录。这样每个 container 的网络就能隔离开来。 docker 默认采用 veth 的方式将 container 中的虚拟网卡同 host 上的一个 docker bridge 连接在一起。

    参考文档:Introduction to Linux namespaces – Part 5: NET

    uts namespace

    UTS ("UNIX Time-sharing System") namespace 允许每个 container 拥有独立的 hostname 和 domain name, 使其在网络上可以被视作一个独立的节点而非 Host 上的一个进程。

    参考文档:Introduction to Linux namespaces – Part 1: UTS

    ipc namespace

    container 中进程交互还是采用 Linux 常见的进程间交互方法 (interprocess communication - IPC), 包括常见的信号量、消息队列和共享内存。然而同 VM 不同,container 的进程间交互实际上还是 host 上具有相同 pid namespace 中的进程间交互,因此需要在IPC资源申请时加入 namespace 信息 - 每个 IPC 资源有一个唯一的 32bit ID。

    参考文档:Introduction to Linux namespaces – Part 2: IPC

    user namespace

    每个 container 可以有不同的 user 和 group id, 也就是说可以以 container 内部的用户在 container 内部执行程序而非 Host 上的用户。

    有了以上 6 种 namespace 从进程、网络、IPC、文件系统、UTS 和用户角度的隔离,一个 container 就可以对外展现出一个独立计算机的能力,并且不同 container 从 OS 层面实现了隔离。 然而不同 namespace 之间资源还是相互竞争的,仍然需要类似 ulimit 来管理每个 container 所能使用的资源 - cgroup。

    Reference

    1.6 资源配额「cgroups」

    cgroups 实现了对资源的配额和度量。 cgroups 的使用非常简单,提供类似文件的接口,在 /cgroup 目录下新建一个文件夹即可新建一个 group,在此文件夹中新建 task 文件,并将 pid 写入该文件,即可实现对该进程的资源控制。具体的资源配置选项可以在该文件夹中新建子 subsystem ,{子系统前缀}.{资源项} 是典型的配置方法, 如 memory.usageinbytes 就定义了该 group 在 subsystem memory 中的一个内存限制选项。 另外,cgroups 中的 subsystem 可以随意组合,一个 subsystem 可以在不同的 group 中,也可以一个 group 包含多个 subsystem - 也就是说一个 subsystem。

    • memory
      • 内存相关的限制
    • cpu
      • 在 cgroup 中,并不能像硬件虚拟化方案一样能够定义 CPU 能力,但是能够定义 CPU 轮转的优先级,因此具有较高 CPU 优先级的进程会更可能得到 CPU 运算。 通过将参数写入 cpu.shares ,即可定义改 cgroup 的 CPU 优先级 - 这里是一个相对权重,而非绝对值
    • blkio
      • block IO 相关的统计和限制,byte/operation 统计和限制 (IOPS 等),读写速度限制等,但是这里主要统计的都是同步 IO
    • devices
      • 设备权限限制

    参考文档:how to use cgroup

    二、Docker 安装

    docker 的相关安装方法这里不作介绍,具体安装参考 官档

    获取当前 docker 版本

    $ sudo docker version
    Client version: 1.3.2
    Client API version: 1.15
    Go version (client): go1.3.3
    Git commit (client): 39fa2fa/1.3.2
    OS/Arch (client): linux/amd64
    Server version: 1.3.2
    Server API version: 1.15
    Go version (server): go1.3.3
    Git commit (server): 39fa2fa/1.3.2

    三、Docker 基础用法

    Docker HUB : Docker镜像首页,包括官方镜像和其它公开镜像

    因为国情的原因,国内下载 Docker HUB 官方的相关镜像比较慢,可以使用 docker.cn 镜像,镜像保持和官方一致,关键是速度块,推荐使用。

    3.1 Search images

    $ sudo docker search ubuntu

    3.2 Pull images

    $ sudo docker pull ubuntu # 获取 ubuntu 官方镜像 $ sudo docker images # 查看当前镜像列表 

    3.3 Running an interactive shell

    $ sudo docker run -i -t ubuntu:14.04 /bin/bash
    • docker run - 运行一个容器
    • -t - 分配一个(伪)tty (link is external)
    • -i - 交互模式 (so we can interact with it)
    • ubuntu:14.04 - 使用 ubuntu 基础镜像 14.04
    • /bin/bash - 运行命令 bash shell

    注: ubuntu 会有多个版本,通过指定 tag 来启动特定的版本 [image]:[tag]

    $ sudo docker ps # 查看当前运行的容器, ps -a 列出当前系统所有的容器 CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
    6c9129e9df10        ubuntu:14.04        /bin/bash 6 minutes ago       Up 6 minutes                            cranky_babbage

    3.4 相关快捷键

    • 退出:Ctrl-Dorexit
    • detach:Ctrl-P + Ctrl-Q
    • attach:docker attach CONTAINER-ID

    四、Docker 命令帮助

    4.1 docker help

    docker command

    $ sudo docker   # docker 命令帮助
    

    Commands:
    attach Attach to a running container # 当前 shell 下 attach 连接指定运行镜像
    build Build an image from a Dockerfile # 通过 Dockerfile 定制镜像
    commit Create a new image from a container’s changes # 提交当前容器为新的镜像
    cp Copy files/folders from the containers filesystem to the host path
    # 从容器中拷贝指定文件或者目录到宿主机中
    create Create a new container # 创建一个新的容器,同 run,但不启动容器
    diff Inspect changes on a container’s filesystem # 查看 docker 容器变化
    events Get real time events from the server # 从 docker 服务获取容器实时事件
    exec Run a command in an existing container # 在已存在的容器上运行命令
    export Stream the contents of a container as a tar archive
    # 导出容器的内容流作为一个 tar 归档文件[对应 import ]
    history Show the history of an image # 展示一个镜像形成历史
    images List images # 列出系统当前镜像
    import Create a new filesystem image from the contents of a tarball
    # 从tar包中的内容创建一个新的文件系统映像[对应 export]
    info Display system-wide information # 显示系统相关信息
    inspect Return low-level information on a container # 查看容器详细信息
    kill Kill a running container # kill 指定 docker 容器
    load Load an image from a tar archive # 从一个 tar 包中加载一个镜像[对应 save]
    login Register or Login to the docker registry server
    # 注册或者登陆一个 docker 源服务器
    logout Log out from a Docker registry server # 从当前 Docker registry 退出
    logs Fetch the logs of a container # 输出当前容器日志信息
    port Lookup the public-facing port which is NAT-ed to PRIVATE_PORT
    # 查看映射端口对应的容器内部源端口
    pause Pause all processes within a container # 暂停容器
    ps List containers # 列出容器列表
    pull Pull an image or a repository from the docker registry server
    # 从docker镜像源服务器拉取指定镜像或者库镜像
    push Push an image or a repository to the docker registry server
    # 推送指定镜像或者库镜像至docker源服务器
    restart Restart a running container # 重启运行的容器
    rm Remove one or more containers # 移除一个或者多个容器
    rmi Remove one or more images
    # 移除一个或多个镜像[无容器使用该镜像才可删除,否则需删除相关容器才可继续或 -f 强制删除]
    run Run a command in a new container
    # 创建一个新的容器并运行一个命令
    save Save an image to a tar archive # 保存一个镜像为一个 tar 包[对应 load]
    search Search for an image on the Docker Hub # 在 docker hub 中搜索镜像
    start Start a stopped containers # 启动容器
    stop Stop a running containers # 停止容器
    tag Tag an image into a repository # 给源中镜像打标签
    top Lookup the running processes of a container # 查看容器中运行的进程信息
    unpause Unpause a paused container # 取消暂停容器
    version Show the docker version information # 查看 docker 版本号
    wait Block until a container stops, then print its exit code
    # 截取容器停止时的退出状态值
    Run ‘docker COMMAND --help’ for more information on a command.

    docker option

    Usage of docker:
      --api-enable-cors=false                Enable CORS headers in the remote API                      # 远程 API 中开启 CORS 头
      -b, --bridge=""                        Attach containers to a pre-existing network bridge         # 桥接网络
                                               use 'none' to disable container networking
      --bip=""                               Use this CIDR notation address for the network bridge's IP, not compatible with -b
                                             # 和 -b 选项不兼容,具体没有测试过
      -d, --daemon=false                     Enable daemon mode                                         # daemon 模式
      -D, --debug=false                      Enable debug mode                                          # debug 模式
      --dns=[]                               Force docker to use specific DNS servers                   # 强制 docker 使用指定 dns 服务器
      --dns-search=[]                        Force Docker to use specific DNS search domains            # 强制 docker 使用指定 dns 搜索域
      -e, --exec-driver="native"             Force the docker runtime to use a specific exec driver     # 强制 docker 运行时使用指定执行驱动器
      --fixed-cidr=""                        IPv4 subnet for fixed IPs (ex: 10.20.0.0/16)
                                               this subnet must be nested in the bridge subnet (which is defined by -b or --bip)
      -G, --group="docker"                   Group to assign the unix socket specified by -H when running in daemon mode
                                               use '' (the empty string) to disable setting of a group
      -g, --graph="/var/lib/docker"          Path to use as the root of the docker runtime              # 容器运行的根目录路径
      -H, --host=[]                          The socket(s) to bind to in daemon mode                    # daemon 模式下 docker 指定绑定方式[tcp or 本地 socket]
                                               specified using one or more tcp://host:port, unix:///path/to/socket, fd://* or fd://socketfd.
      --icc=true                             Enable inter-container communication                       # 跨容器通信
      --insecure-registry=[]                 Enable insecure communication with specified registries (no certificate verification for HTTPS and enable HTTP fallback) (e.g., localhost:5000 or 10.20.0.0/16)
      --ip="0.0.0.0"                         Default IP address to use when binding container ports     # 指定监听地址,默认所有 ip
      --ip-forward=true                      Enable net.ipv4.ip_forward                                 # 开启转发
      --ip-masq=true                         Enable IP masquerading for bridge's IP range
      --iptables=true                        Enable Docker's addition of iptables rules                 # 添加对应 iptables 规则
      --mtu=0                                Set the containers network MTU                             # 设置网络 mtu
                                               if no value is provided: default to the default route MTU or 1500 if no default route is available
      -p, --pidfile="/var/run/docker.pid"    Path to use for daemon PID file                            # 指定 pid 文件位置
      --registry-mirror=[]                   Specify a preferred Docker registry mirror                  
      -s, --storage-driver=""                Force the docker runtime to use a specific storage driver  # 强制 docker 运行时使用指定存储驱动
      --selinux-enabled=false                Enable selinux support                                     # 开启 selinux 支持
      --storage-opt=[]                       Set storage driver options                                 # 设置存储驱动选项
      --tls=false                            Use TLS; implied by tls-verify flags                       # 开启 tls
      --tlscacert="/root/.docker/ca.pem"     Trust only remotes providing a certificate signed by the CA given here
      --tlscert="/root/.docker/cert.pem"     Path to TLS certificate file                               # tls 证书文件位置
      --tlskey="/root/.docker/key.pem"       Path to TLS key file                                       # tls key 文件位置
      --tlsverify=false                      Use TLS and verify the remote (daemon: verify client, client: verify daemon) # 使用 tls 并确认远程控制主机
      -v, --version=false                    Print version information and quit                         # 输出 docker 版本信息

    4.2 docker search

    $ sudo docker search --help
    

    Usage: docker search TERM

    Search the Docker Hub for images # 从 Docker Hub 搜索镜像 --automated=false Only show automated builds
    –no-trunc=false Don’t truncate output
    -s, --stars=0 Only displays with at least xxx stars

    示例:

    $ sudo docker search -s 100 ubuntu # 查找 star 数至少为 100 的镜像,找出只有官方镜像 start 数超过 100,默认不加 s 选项找出所有相关 ubuntu 镜像 NAME      DESCRIPTION                  STARS     OFFICIAL   AUTOMATED
    ubuntu    Official Ubuntu base image 425 [OK] 

    4.3 docker info

    $ sudo docker info 
    Containers: 1 # 容器个数 Images: 22 # 镜像个数 Storage Driver: devicemapper # 存储驱动 Pool Name: docker-8:17-3221225728-pool
     Pool Blocksize: 65.54 kB
     Data file: /data/docker/devicemapper/devicemapper/data
     Metadata file: /data/docker/devicemapper/devicemapper/metadata
     Data Space Used: 1.83 GB
     Data Space Total: 107.4 GB
     Metadata Space Used: 2.191 MB
     Metadata Space Total: 2.147 GB
     Library Version: 1.02.84-RHEL7 (2014-03-26) Execution Driver: native-0.2 # 存储驱动 Kernel Version: 3.10.0-123.el7.x86_64
    Operating System: CentOS Linux 7 (Core) 

    4.4 docker pull && docker push

    $ sudo docker pull --help # pull 拉取镜像 Usage: docker pull [OPTIONS] NAME[:TAG] Pull an image or a repository from the registry
    

    -a, --all-tags=false Download all tagged images in the repository $ sudo docker push # push 推送指定镜像 Usage: docker push NAME[:TAG] Push an image or a repository to the registry

    示例:

    $ sudo docker pull ubuntu # 下载官方 ubuntu docker 镜像,默认下载所有 ubuntu 官方库镜像 $ sudo docker pull ubuntu:14.04 # 下载指定版本 ubuntu 官方镜像 
    $ sudo docker push 192.168.0.100:5000/ubuntu # 推送镜像库到私有源[可注册 docker 官方账户,推送到官方自有账户] $ sudo docker push 192.168.0.100:5000/ubuntu:14.04 # 推送指定镜像到私有源 

    4.5 docker images

    列出当前系统镜像

    $ sudo docker images --help
    

    Usage: docker images [OPTIONS] [NAME] List images

    -a, --all=false Show all images (by default filter out the intermediate image layers) # -a 显示当前系统的所有镜像,包括过渡层镜像,默认 docker images 显示最终镜像,不包括过渡层镜像 -f, --filter=[] Provide filter values (i.e. ‘dangling=true’) --no-trunc=false Don’t truncate output
    -q, --quiet=false Only show numeric IDs

    示例:

    $ sudo docker images # 显示当前系统镜像,不包括过渡层镜像 $ sudo docker images -a # 显示当前系统所有镜像,包括过渡层镜像 $ sudo docker images ubuntu # 显示当前系统 docker ubuntu 库中的所有镜像 REPOSITORY                 TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
    ubuntu                     12.04               ebe4be4dd427 4 weeks ago         210.6 MB
    ubuntu                     14.04               e54ca5efa2e9 4 weeks ago         276.5 MB
    ubuntu                     14.04-ssh           6334d3ac099a 7 weeks ago         383.2 MB

    4.6 docker rmi

    删除一个或者多个镜像

    $ sudo docker rmi --help
    

    Usage: docker rmi IMAGE [IMAGE…] Remove one or more images

    -f, --force=false Force removal of the image # 强制移除镜像不管是否有容器使用该镜像 --no-prune=false Do not delete untagged parents # 不要删除未标记的父镜像

    4.7 docker run

    $ sudo docker run --help
    

    Usage: docker run [OPTIONS] IMAGE [COMMAND] [ARG…] Run a command in a new container

    -a, --attach=[] Attach to stdin, stdout or stderr.
    -c, --cpu-shares=0 CPU shares (relative weight) # 设置 cpu 使用权重 --cap-add=[] Add Linux capabilities
    –cap-drop=[] Drop Linux capabilities
    –cidfile="" Write the container ID to the file # 把容器 id 写入到指定文件 --cpuset="" CPUs in which to allow execution (0-3, 0,1) # cpu 绑定 -d, --detach=false Detached mode: Run container in the background, print new container id # 后台运行容器 --device=[] Add a host device to the container (e.g. --device=/dev/sdc:/dev/xvdc) --dns=[] Set custom dns servers # 设置 dns --dns-search=[] Set custom dns search domains # 设置 dns 域搜索 -e, --env=[] Set environment variables # 定义环境变量 --entrypoint="" Overwrite the default entrypoint of the image # ? --env-file=[] Read in a line delimited file of ENV variables # 从指定文件读取变量值 --expose=[] Expose a port from the container without publishing it to your host # 指定对外提供服务端口 -h, --hostname="" Container host name # 设置容器主机名 -i, --interactive=false Keep stdin open even if not attached # 保持标准输出开启即使没有 attached --link=[] Add link to another container (name:alias) # 添加链接到另外一个容器 --lxc-conf=[] (lxc exec-driver only) Add custom lxc options --lxc-conf=“lxc.cgroup.cpuset.cpus = 0,1” -m, --memory="" Memory limit (format: <number><optional unit>, where unit = b, k, m or g) # 内存限制 --name="" Assign a name to the container # 设置容器名 --net=“bridge” Set the Network mode for the container # 设置容器网络模式 ‘bridge’: creates a new network stack for the container on the docker bridge ‘none’: no networking for this container ‘container:<name|id>’: reuses another container network stack ‘host’: use the host network stack inside the container. Note: the host mode gives the container full access to local system services such as D-bus and is therefore considered insecure.
    -P, --publish-all=false Publish all exposed ports to the host interfaces # 自动映射容器对外提供服务的端口 -p, --publish=[] Publish a container’s port to the host # 指定端口映射 format: ip:hostPort:containerPort | ip::containerPort | hostPort:containerPort (use ‘docker port’ to see the actual mapping) --privileged=false Give extended privileges to this container # 提供更多的权限给容器 --restart="" Restart policy to apply when a container exits (no, on-failure[:max-retry], always) --rm=false Automatically remove the container when it exits (incompatible with -d) # 如果容器退出自动移除和 -d 选项冲突 --security-opt=[] Security Options
    –sig-proxy=true Proxify received signals to the process (even in non-tty mode). SIGCHLD is not proxied.
    -t, --tty=false Allocate a pseudo-tty # 分配伪终端 -u, --user="" Username or UID # 指定运行容器的用户 uid 或者用户名 -v, --volume=[] Bind mount a volume (e.g., from the host: -v /host:/container, from docker: -v /container) # 挂载卷 --volumes-from=[] Mount volumes from the specified container(s) # 从指定容器挂载卷 -w, --workdir="" Working directory inside the container # 指定容器工作目录

    示例:

    $ sudo docker images ubuntu
    REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
    ubuntu              14.04               e54ca5efa2e9 4 weeks ago         276.5 MB
    ... ... $ sudo docker run -t -i -c 100 -m 512MB -h test1 -d --name="docker_test1" ubuntu /bin/bash # 创建一个 cpu 优先级为 100,内存限制 512MB,主机名为 test1,名为 docker_test1 后台运行 bash 的容器 a424ca613c9f2247cd3ede95adfbaf8d28400cbcb1d5f9b69a7b56f97b2b52e5 $ sudo docker ps 
    CONTAINER ID        IMAGE           COMMAND         CREATED             STATUS              PORTS       NAMES
    a424ca613c9f        ubuntu:14.04    /bin/bash 6 seconds ago       Up 5 seconds                    docker_test1 $ sudo docker attach docker_test1
    root@test1:/# pwd /
    root@test1:/# exit exit 

    关于cpu优先级:

    By default all groups have 1024 shares. A group with 100 shares will get a ~10% portion of the CPU time - archlinux cgroups

    4.8 docker start|stop|kill... ...

    dockerstart|stop|kill|restart|pause|unpause|rm|commit|inspect|logs

    • docker start CONTAINER [CONTAINER...]
      • # 运行一个或多个停止的容器
    • docker stop CONTAINER [CONTAINER...]
      • # 停掉一个或多个运行的容器-t选项可指定超时时间
    • docker kill [OPTIONS] CONTAINER [CONTAINER...]
      • # 默认 kill 发送 SIGKILL 信号-s可以指定发送 kill 信号类型
    • docker restart [OPTIONS] CONTAINER [CONTAINER...]
      • # 重启一个或多个运行的容器-t选项可指定超时时间
    • docker pause CONTAINER
      • # 暂停一个容器,方便 commit
    • docker unpause CONTAINER
      • # 继续暂停的容器
    • docker rm [OPTIONS] CONTAINER [CONTAINER...]
      • # 移除一个或多个容器
      • -f, --force=false Force removal of running container
      • -l, --link=false Remove the specified link and not the underlying container
      • -v, --volumes=false Remove the volumes associated with the container
    • docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
      • # 提交指定容器为镜像
      • -a, --author="" Author (e.g., "John Hannibal Smith hannibal@a-team.com")
      • -m, --message="" Commit message
      • -p, --pause=true Pause container during commit
        • # 默认 commit 是暂停状态
    • docker inspect CONTAINER|IMAGE [CONTAINER|IMAGE...]
      • # 查看容器或者镜像的详细信息
    • docker logs CONTAINER
      • # 输出指定容器日志信息
      • -f, --follow=false Follow log output
        • # 类似 tail -f
      • -t, --timestamps=false Show timestamps
      • --tail="all" Output the specified number of lines at the end of logs (defaults to all logs)

    参考文档:Docker Run Reference

    4.9 Docker 1.3 新增特性和命令

    Digital Signature Verification

    Docker 1.3 版本将使用数字签名自动验证所有官方库的来源和完整性,如果一个官方镜像被篡改或者被破坏,目前 Docker 只会对这种情况发出警告而并不阻止容器的运行。

    Inject new processes withdocker exec

    docker exec --help
    

    Usage: docker exec [OPTIONS] CONTAINER COMMAND [ARG…] Run a command in an existing container

    -d, --detach=false Detached mode: run command in the background
    -i, --interactive=false Keep STDIN open even if not attached
    -t, --tty=false Allocate a pseudo-TTY

    为了简化调试,可以使用docker exec命令通过 Docker API 和 CLI 在运行的容器上运行程序。

    $ docker exec -it ubuntu_bash bash

    上例将在容器 ubuntu_bash 中创建一个新的 Bash 会话。

    Tune container lifecycles withdocker create

    我们可以通过docker run <image name>命令创建一个容器并运行其中的程序,因为有很多用户要求创建容器的时候不启动容器,所以docker create应运而生了。

    $ docker create -t -i fedora bash
    6d8af538ec541dd581ebc2a24153a28329acb5268abe5ef868c1f1a261221752

    上例创建了一个可写的容器层 (并且打印出容器 ID),但是并不运行它,可以使用以下命令运行该容器:

    $ docker start -a -i 6d8af538ec5
    bash-4.2#

    Security Options

    通过--security-opt选项,运行容器时用户可自定义 SELinux 和 AppArmor 卷标和配置。

    $ docker run --security-opt label:type:svirt_apache -i -t centos \ bash

    上例只允许容器监听在 Apache 端口,这个选项的好处是用户不需要运行 docker 的时候指定--privileged选项,降低安全风险。

    参考文档:Docker 1.3: signed images, process injection, security options, Mac shared directories

    4.10 Docker 1.5 新特性

    参考文档:Docker 1.5 新特性

    五、Docker 端口映射

    # Find IP address of container with ID <container_id> 通过容器 id 获取 ip $ sudo docker inspect <container_id> | grep IPAddress | cut -d ’"’ -f 4

    无论如何,这些 ip 是基于本地系统的并且容器的端口非本地主机是访问不到的。此外,除了端口只能本地访问外,对于容器的另外一个问题是这些 ip 在容器每次启动的时候都会改变。

    Docker 解决了容器的这两个问题,并且给容器内部服务的访问提供了一个简单而可靠的方法。Docker 通过端口绑定主机系统的接口,允许非本地客户端访问容器内部运行的服务。为了简便的使得容器间通信,Docker 提供了这种连接机制。

    5.1 自动映射端口

    -P使用时需要指定--expose选项,指定需要对外提供服务的端口

    $ sudo docker run -t -P --expose 22 --name server  ubuntu:14.04

    使用docker run -P自动绑定所有对外提供服务的容器端口,映射的端口将会从没有使用的端口池中 (49000..49900) 自动选择,你可以通过docker ps、docker inspect <container_id>或者docker port <container_id> <port>确定具体的绑定信息。

    5.2 绑定端口到指定接口

    基本语法

    $ sudo docker run -p [([<host_interface>:[host_port]])|(<host_port>):]<container_port>[/udp] <image> <cmd>

    默认不指定绑定 ip 则监听所有网络接口。

    绑定 TCP 端口

    # Bind TCP port 8080 of the container to TCP port 80 on 127.0.0.1 of the host machine. $ sudo docker run -p 127.0.0.1:80:8080 <image> <cmd> # Bind TCP port 8080 of the container to a dynamically allocated TCP port on 127.0.0.1 of the host machine. $ sudo docker run -p 127.0.0.1::8080 <image> <cmd> # Bind TCP port 8080 of the container to TCP port 80 on all available interfaces of the host machine. $ sudo docker run -p 80:8080 <image> <cmd> # Bind TCP port 8080 of the container to a dynamically allocated TCP port on all available interfaces $ sudo docker run -p 8080 <image> <cmd>

    绑定 UDP 端口

    # Bind UDP port 5353 of the container to UDP port 53 on 127.0.0.1 of the host machine. $ sudo docker run -p 127.0.0.1:53:5353/udp <image> <cmd>

    六、Docker 网络配置

    非常详细的 Docker 学习笔记

    图: Docker - container and lightweight virtualization

    Dokcer 通过使用 Linux 桥接提供容器之间的通信,docker0 桥接接口的目的就是方便 Docker 管理。当 Docker daemon 启动时需要做以下操作:

    • creates the docker0 bridge if not present
      • # 如果 docker0 不存在则创建
    • searches for an IP address range which doesn’t overlap with an existing route
      • # 搜索一个与当前路由不冲突的 ip 段
    • picks an IP in the selected range
      • # 在确定的范围中选择 ip
    • assigns this IP to the docker0 bridge
      • # 绑定 ip 到 docker0

    6.1 Docker 四种网络模式

    四种网络模式摘自 Docker 网络详解及 pipework 源码解读与实践

    docker run 创建 Docker 容器时,可以用 --net 选项指定容器的网络模式,Docker 有以下 4 种网络模式:

    • host 模式,使用 --net=host 指定。
    • container 模式,使用 --net=container:NAMEorID 指定。
    • none 模式,使用 --net=none 指定。
    • bridge 模式,使用 --net=bridge 指定,默认设置。

    host 模式

    如果启动容器的时候使用 host 模式,那么这个容器将不会获得一个独立的 Network Namespace,而是和宿主机共用一个 Network Namespace。容器将不会虚拟出自己的网卡,配置自己的 IP 等,而是使用宿主机的 IP 和端口。

    例如,我们在 10.10.101.105/24 的机器上用 host 模式启动一个含有 web 应用的 Docker 容器,监听 tcp 80 端口。当我们在容器中执行任何类似 ifconfig 命令查看网络环境时,看到的都是宿主机上的信息。而外界访问容器中的应用,则直接使用 10.10.101.105:80 即可,不用任何 NAT 转换,就如直接跑在宿主机中一样。但是,容器的其他方面,如文件系统、进程列表等还是和宿主机隔离的。

    container 模式

    这个模式指定新创建的容器和已经存在的一个容器共享一个 Network Namespace,而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的 IP,而是和一个指定的容器共享 IP、端口范围等。同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。两个容器的进程可以通过 lo 网卡设备通信。

    none模式

    这个模式和前两个不同。在这种模式下,Docker 容器拥有自己的 Network Namespace,但是,并不为 Docker容器进行任何网络配置。也就是说,这个 Docker 容器没有网卡、IP、路由等信息。需要我们自己为 Docker 容器添加网卡、配置 IP 等。

    bridge模式

    非常详细的 Docker 学习笔记

    图:The Container World | Part 2 Networking

    bridge 模式是 Docker 默认的网络设置,此模式会为每一个容器分配 Network Namespace、设置 IP 等,并将一个主机上的 Docker 容器连接到一个虚拟网桥上。当 Docker server 启动时,会在主机上创建一个名为 docker0 的虚拟网桥,此主机上启动的 Docker 容器会连接到这个虚拟网桥上。虚拟网桥的工作方式和物理交换机类似,这样主机上的所有容器就通过交换机连在了一个二层网络中。接下来就要为容器分配 IP 了,Docker 会从 RFC1918 所定义的私有 IP 网段中,选择一个和宿主机不同的IP地址和子网分配给 docker0,连接到 docker0 的容器就从这个子网中选择一个未占用的 IP 使用。如一般 Docker 会使用 172.17.0.0/16 这个网段,并将 172.17.42.1/16 分配给 docker0 网桥(在主机上使用 ifconfig 命令是可以看到 docker0 的,可以认为它是网桥的管理接口,在宿主机上作为一块虚拟网卡使用)

    6.2 列出当前主机网桥

    $ sudo brctl show # brctl 工具依赖 bridge-utils 软件包 bridge name bridge id STP enabled interfaces
    docker0 8000.000000000000 no

    6.3 查看当前 docker0 ip

    $ sudo ifconfig docker0
    docker0 Link encap:Ethernet HWaddr xx:xx:xx:xx:xx:xx
    inet addr:172.17.42.1 Bcast:0.0.0.0 Mask:255.255.0.0

    在容器运行时,每个容器都会分配一个特定的虚拟机口并桥接到 docker0。每个容器都会配置同 docker0 ip 相同网段的专用 ip 地址,docker0 的 IP 地址被用于所有容器的默认网关。

    6.4 运行一个容器

    $ sudo docker run -t -i -d ubuntu /bin/bash
    52f811c5d3d69edddefc75aff5a4525fc8ba8bcfa1818132f9dc7d4f7c7e78b4 $ sudo brctl show
    bridge name bridge id STP enabled interfaces
    docker0 8000.fef213db5a66 no vethQCDY1N

    以上, docker0 扮演着 52f811c5d3d6 container 这个容器的虚拟接口 vethQCDY1N interface 桥接的角色。

    使用特定范围的 IP

    Docker 会尝试寻找没有被主机使用的 ip 段,尽管它适用于大多数情况下,但是它不是万能的,有时候我们还是需要对 ip 进一步规划。Docker 允许你管理 docker0 桥接或者通过-b选项自定义桥接网卡,需要安装bridge-utils软件包。

    基本步骤如下:

    • ensure Docker is stopped
      • # 确保 docker 的进程是停止的
    • create your own bridge (bridge0 for example)
      • # 创建自定义网桥
    • assign a specific IP to this bridge
      • # 给网桥分配特定的 ip
    • start Docker with the -b=bridge0 parameter
      • # 以 -b 的方式指定网桥
    # Stopping Docker and removing docker0 $ sudo service docker stop $ sudo ip link set dev docker0 down $ sudo brctl delbr docker0 # Create our own bridge $ sudo brctl addbr bridge0 $ sudo ip addr add 192.168.5.1/24 dev bridge0 $ sudo ip link set dev bridge0 up # Confirming that our bridge is up and running $ ip addr show bridge0
    4: bridge0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state UP group default
        link/ether 66:38:d0:0d:76:18 brd ff:ff:ff:ff:ff:ff
        inet 192.168.5.1/24 scope global bridge0
           valid_lft forever preferred_lft forever # Tell Docker about it and restart (on Ubuntu) $ echo 'DOCKER_OPTS="-b=bridge0"' >> /etc/default/docker $ sudo service docker start

    参考文档: Network Configuration

    6.5 不同主机间容器通信

    不同容器之间的通信可以借助于 pipework 这个工具:

    $ git clone https://github.com/jpetazzo/pipework.git
    $ sudo cp -rp pipework/pipework /usr/local/bin/

    安装相应依赖软件

    $ sudo apt-get install iputils-arping bridge-utils -y

    桥接网络

    桥接网络可以参考 日常问题处理 Tips 关于桥接的配置说明,这里不再赘述。

    # brctl show
    bridge name     bridge id               STP enabled     interfaces
    br0             8000.000c291412cd       no              eth0
    docker0         8000.56847afe9799       no              vetheb48029

    可以删除 docker0,直接把 docker 的桥接指定为 br0。也可以保留使用默认的配置,这样单主机容器之间的通信可以通过 docker0,而跨主机不同容器之间通过 pipework 新建 docker 容器的网卡桥接到 br0,这样跨主机容器之间就可以通信了。

    • ubuntu
    $ sudo service docker stop
    $ sudo ip link set dev docker0 down
    $ sudo brctl delbr docker0
    $ echo 'DOCKER_OPTS="-b=br0"' >> /etc/default/docker
    $ sudo service docker start
    • CentOS 7/RHEL 7
    $ sudo systemctl stop docker
    $ sudo ip link set dev docker0 down
    $ sudo brctl delbr docker0
    $ cat /etc/sysconfig/docker | grep 'OPTIONS='
    OPTIONS=--selinux-enabled -b=br0 -H fd://
    $ sudo systemctl start docker

    pipework

    非常详细的 Docker 学习笔记

    不同容器之间的通信可以借助于 pipework 这个工具给 docker 容器新建虚拟网卡并绑定 IP 桥接到 br0

    $ git clone https://github.com/jpetazzo/pipework.git
    $ sudo cp -rp pipework/pipework /usr/local/bin/
    $ pipework 
    Syntax:
    pipework <hostinterface> [-i containerinterface] <guest> <ipaddr>/<subnet>[@default_gateway] [macaddr][@vlan]
    pipework <hostinterface> [-i containerinterface] <guest> dhcp [macaddr][@vlan]
    pipework --wait [-i containerinterface]

    如果删除了默认的 docker0 桥接,把 docker 默认桥接指定到了 br0,则最好在创建容器的时候加上--net=none,防止自动分配的 IP 在局域网中有冲突。

    $ sudo docker run --rm -ti --net=none ubuntu:14.04 /bin/bash
    root@a46657528059:/#
    $                  # Ctrl-P + Ctrl-Q 回到宿主机 shell,容器 detach 状态
    $ sudo docker  ps
    CONTAINER ID    IMAGE          COMMAND       CREATED         STATUS          PORTS      NAMES
    a46657528059    ubuntu:14.04   "/bin/bash"   4 minutes ago   Up 4 minutes               hungry_lalande
    $ sudo pipework br0 -i eth0 a46657528059 192.168.115.10/24@192.168.115.2 
    # 默认不指定网卡设备名,则默认添加为 eth1
    # 另外 pipework 不能添加静态路由,如果有需求则可以在 run 的时候加上 --privileged=true 权限在容器中手动添加,
    # 但这种安全性有缺陷,可以通过 ip netns 操作
    $ sudo docker attach a46657528059
    root@a46657528059:/# ifconfig eth0
    eth0      Link encap:Ethernet  HWaddr 86:b6:6b:e8:2e:4d  
              inet addr:192.168.115.10  Bcast:0.0.0.0  Mask:255.255.255.0
              inet6 addr: fe80::84b6:6bff:fee8:2e4d/64 Scope:Link
              UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
              RX packets:8 errors:0 dropped:0 overruns:0 frame:0
              TX packets:9 errors:0 dropped:0 overruns:0 carrier:0
              collisions:0 txqueuelen:1000 
              RX bytes:648 (648.0 B)  TX bytes:690 (690.0 B)
    

    root@a46657528059:/# route -n
    Kernel IP routing table
    Destination Gateway Genmask Flags Metric Ref Use Iface
    0.0.0.0 192.168.115.2 0.0.0.0 UG 0 0 0 eth0
    192.168.115.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0

    使用ip netns添加静态路由,避免创建容器使用--privileged=true选项造成一些不必要的安全问题:

    $ docker inspect --format="{{ .State.Pid }}" a46657528059 # 获取指定容器 pid
    6350
    $ sudo ln -s /proc/6350/ns/net /var/run/netns/6350
    $ sudo ip netns exec 6350 ip route add 192.168.0.0/16 dev eth0 via 192.168.115.2
    $ sudo ip netns exec 6350 ip route    # 添加成功
    192.168.0.0/16 via 192.168.115.2 dev eth0 
    ... ...

    在其它宿主机进行相应的配置,新建容器并使用 pipework 添加虚拟网卡桥接到 br0,测试通信情况即可。

    另外,pipework 可以创建容器的 vlan 网络,这里不作过多的介绍了,官方文档已经写的很清楚了,可以查看以下两篇文章:

    七、Dockerfile

    Docker 可以通过 Dockerfile 的内容来自动构建镜像。Dockerfile 是一个包含创建镜像所有命令的文本文件,通过docker build命令可以根据 Dockerfile 的内容构建镜像,在介绍如何构建之前先介绍下 Dockerfile 的基本语法结构。

    Dockerfile 有以下指令选项:

    • FROM
    • MAINTAINER
    • RUN
    • CMD
    • EXPOSE
    • ENV
    • ADD
    • COPY
    • ENTRYPOINT
    • VOLUME
    • USER
    • WORKDIR
    • ONBUILD

    7.1 FROM

    用法:

    FROM <image>

    或者

    FROM <image>
    • FROM指定构建镜像的基础源镜像,如果本地没有指定的镜像,则会自动从 Docker 的公共库 pull 镜像下来。
    • FROM必须是 Dockerfile 中非注释行的第一个指令,即一个 Dockerfile 从FROM语句开始。
    • FROM可以在一个 Dockerfile 中出现多次,如果有需求在一个 Dockerfile 中创建多个镜像。
    • 如果FROM语句没有指定镜像标签,则默认使用latest标签。

    7.2 MAINTAINER

    用法:

    MAINTAINER <name>

    指定创建镜像的用户

    RUN 有两种使用方式

    每条RUN指令将在当前镜像基础上执行指定命令,并提交为新的镜像,后续的RUN都在之前RUN提交后的镜像为基础,镜像是分层的,可以通过一个镜像的任何一个历史提交点来创建,类似源码的版本控制。

    exec 方式会被解析为一个 JSON 数组,所以必须使用双引号而不是单引号。exec 方式不会调用一个命令 shell,所以也就不会继承相应的变量,如:

    RUN [ "echo", "$HOME" ]

    这种方式是不会达到输出 HOME 变量的,正确的方式应该是这样的

    RUN [ "sh", "-c", "echo", "$HOME" ]

    RUN产生的缓存在下一次构建的时候是不会失效的,会被重用,可以使用--no-cache选项,即docker build --no-cache,如此便不会缓存。

    7.3 CMD

    CMD有三种使用方式:

    CMD指定在 Dockerfile 中只能使用一次,如果有多个,则只有最后一个会生效。

    CMD的目的是为了在启动容器时提供一个默认的命令执行选项。如果用户启动容器时指定了运行的命令,则会覆盖掉CMD指定的命令。

    CMD会在启动容器的时候执行,build 时不执行,而RUN只是在构建镜像的时候执行,后续镜像构建完成之后,启动容器就与RUN无关了,这个初学者容易弄混这个概念,这里简单注解一下。

    7.4 EXPOSE

    EXPOSE <port> [<port>...]

    告诉 Docker 服务端容器对外映射的本地端口,需要在 docker run 的时候使用-p或者-P选项生效。

    7.5 ENV

    ENV <key> <value>       # 只能设置一个变量
    ENV <key>=<value> ...   # 允许一次设置多个变量

    指定一个环节变量,会被后续RUN指令使用,并在容器运行时保留。

    例子:

    ENV myName="John Doe" myDog=Rex\ The\ Dog \
        myCat=fluffy

    等同于

    ENV myName John Doe
    ENV myDog Rex The Dog
    ENV myCat fluffy

    7.6 ADD

    ADD <src>... <dest>

    ADD复制本地主机文件、目录或者远程文件 URLS 从 并且添加到容器指定路径中 。

    支持通过 GO 的正则模糊匹配,具体规则可参见 Go filepath.Match

    ADD hom* /mydir/        # adds all files starting with "hom"
    ADD hom?.txt /mydir/    # ? is replaced with any single character
    • 路径必须是绝对路径,如果 不存在,会自动创建对应目录
    • 路径必须是 Dockerfile 所在路径的相对路径
    • 如果是一个目录,只会复制目录下的内容,而目录本身则不会被复制

    7.7 COPY

    COPY <src>... <dest>

    COPY复制新文件或者目录从 并且添加到容器指定路径中 。用法同ADD,唯一的不同是不能指定远程文件 URLS。

    7.8 ENTRYPOINT

    配置容器启动后执行的命令,并且不可被 docker run 提供的参数覆盖,而CMD是可以被覆盖的。如果需要覆盖,则可以使用docker run --entrypoint选项。

    每个 Dockerfile 中只能有一个ENTRYPOINT,当指定多个时,只有最后一个生效。

    Exec form ENTRYPOINT 例子

    通过ENTRYPOINT使用 exec form 方式设置稳定的默认命令和选项,而使用CMD添加默认之外经常被改动的选项。

    FROM ubuntu
    ENTRYPOINT ["top", "-b"]
    CMD ["-c"]

    通过 Dockerfile 使用ENTRYPOINT展示前台运行 Apache 服务

    FROM debian:stable
    RUN apt-get update && apt-get install -y --force-yes apache2
    EXPOSE 80 443
    VOLUME ["/var/www", "/var/log/apache2", "/etc/apache2"]
    ENTRYPOINT ["/usr/sbin/apache2ctl", "-D", "FOREGROUND"]

    Shell form ENTRYPOINT 例子

    这种方式会在/bin/sh -c中执行,会忽略任何CMD或者docker run命令行选项,为了确保docker stop能够停止长时间运行ENTRYPOINT的容器,确保执行的时候使用exec选项。

    FROM ubuntu
    ENTRYPOINT exec top -b

    如果在ENTRYPOINT忘记使用exec选项,则可以使用CMD补上:

    FROM ubuntu
    ENTRYPOINT top -b
    CMD --ignored-param1 # --ignored-param2 ... --ignored-param3 ... 依此类推

    7.9 VOLUME

    VOLUME ["/data"]

    创建一个可以从本地主机或其他容器挂载的挂载点,后续具体介绍。

    7.10 USER

    USER daemon

    指定运行容器时的用户名或 UID,后续的RUN、CMD、ENTRYPOINT也会使用指定用户。

    7.11 WORKDIR

    WORKDIR /path/to/workdir

    为后续的RUN、CMD、ENTRYPOINT指令配置工作目录。可以使用多个WORKDIR指令,后续命令如果参数是相对路径,则会基于之前命令指定的路径。

    WORKDIR /a
    WORKDIR b
    WORKDIR c
    RUN pwd

    最终路径是/a/b/c。

    WORKDIR指令可以在ENV设置变量之后调用环境变量:

    ENV DIRPATH /path
    WORKDIR $DIRPATH/$DIRNAME

    最终路径则为 /path/$DIRNAME。

    7.12 ONBUILD

    ONBUILD [INSTRUCTION]

    配置当所创建的镜像作为其它新创建镜像的基础镜像时,所执行的操作指令。

    例如,Dockerfile 使用如下的内容创建了镜像 image-A:

    [...]
    ONBUILD ADD . /app/src
    ONBUILD RUN /usr/local/bin/python-build --dir /app/src
    [...]

    如果基于 image-A 创建新的镜像时,新的 Dockerfile 中使用 FROM image-A 指定基础镜像时,会自动执行 ONBUILD 指令内容,等价于在后面添加了两条指令。

    # Automatically run the following
    ADD . /app/src
    RUN /usr/local/bin/python-build --dir /app/src

    使用ONBUILD指令的镜像,推荐在标签中注明,例如 ruby:1.9-onbuild。

    7.13 Dockerfile Examples

    # Nginx
    #
    # VERSION               0.0.1
    

    FROM ubuntu
    MAINTAINER Victor Vieux <victor@docker.com>

    RUN apt-get update && apt-get install -y inotify-tools nginx apache2 openssh-server

    Firefox over VNC

    VERSION 0.3

    FROM ubuntu

    Install vnc, xvfb in order to create a ‘fake’ display and firefox

    RUN apt-get update && apt-get install -y x11vnc xvfb firefox
    RUN mkdir ~/.vnc

    Setup a password

    RUN x11vnc -storepasswd 1234 ~/.vnc/passwd

    Autostart firefox (might not be the best way, but it does the trick)

    RUN bash -c ‘echo “firefox” >> /.bashrc’

    EXPOSE 5900
    CMD [“x11vnc”, “-forever”, “-usepw”, “-create”]

    Multiple images example

    VERSION 0.1

    FROM ubuntu
    RUN echo foo > bar

    Will output something like ===> 907ad6c2736f

    FROM ubuntu
    RUN echo moo > oink

    Will output something like ===> 695d7793cbe4

    You᾿ll now have two images, 907ad6c2736f with /bar, and 695d7793cbe4 with

    /oink.

    7.14 docker build

    $ docker build --help
    

    Usage: docker build [OPTIONS] PATH | URL | -

    Build a new image from the source code at PATH

    –force-rm=false Always remove intermediate containers, even after unsuccessful builds # 移除过渡容器,即使构建失败
    –no-cache=false Do not use cache when building the image # 不实用 cache
    -q, --quiet=false Suppress the verbose output generated by the containers
    –rm=true Remove intermediate containers after a successful build # 构建成功后移除过渡层容器
    -t, --tag="" Repository name (and optionally a tag) to be applied to the resulting image in case of success

    参考文档:Dockerfile Reference

    7.15 dockerfile 最佳实践

    • 使用.dockerignore文件

    为了在docker build过程中更快上传和更加高效,应该使用一个.dockerignore文件用来排除构建镜像时不需要的文件或目录。例如,除非.git在构建过程中需要用到,否则你应该将它添加到.dockerignore文件中,这样可以节省很多时间。

    • 避免安装不必要的软件包

    为了降低复杂性、依赖性、文件大小以及构建时间,应该避免安装额外的或不必要的包。例如,不需要在一个数据库镜像中安装一个文本编辑器。

    • 每个容器都跑一个进程

    在大多数情况下,一个容器应该只单独跑一个程序。解耦应用到多个容器使其更容易横向扩展和重用。如果一个服务依赖另外一个服务,可以参考 Linking Containers Together

    • 最小化层

    我们知道每执行一个指令,都会有一次镜像的提交,镜像是分层的结构,对于Dockerfile,应该找到可读性和最小化层之间的平衡。

    • 多行参数排序

    如果可能,通过字母顺序来排序,这样可以避免安装包的重复并且更容易更新列表,另外可读性也会更强,添加一个空行使用\换行:

    RUN apt-get update && apt-get install -y \
      bzr \
      cvs \
      git \
      mercurial \
      subversion
    • 创建缓存

    镜像构建过程中会按照Dockerfile的顺序依次执行,每执行一次指令 Docker 会寻找是否有存在的镜像缓存可复用,如果没有则创建新的镜像。如果不想使用缓存,则可以在docker build时添加--no-cache=true选项。

    从基础镜像开始就已经在缓存中了,下一个指令会对比所有的子镜像寻找是否执行相同的指令,如果没有则缓存失效。在大多数情况下只对比Dockerfile指令和子镜像就足够了。ADD和COPY指令除外,执行ADD和COPY时存放到镜像的文件也是需要检查的,完成一个文件的校验之后再利用这个校验在缓存中查找,如果检测的文件改变则缓存失效。RUN apt-get -y update命令只检查命令是否匹配,如果匹配就不会再执行更新了。

    为了有效地利用缓存,你需要保持你的 Dockerfile 一致,并且尽量在末尾修改。

    Dockerfile 指令

    • FROM: 只要可能就使用官方镜像库作为基础镜像
    • RUN: 为保持可读性、方便理解、可维护性,把长或者复杂的RUN语句使用\分隔符分成多行
      • 不建议RUN apt-get update独立成行,否则如果后续包有更新,那么也不会再执行更新
      • 避免使用RUN apt-get upgrade或者dist-upgrade,很多必要的包在一个非privileged权限的容器里是无法升级的。如果知道某个包更新,使用apt-get install -y xxx
      • 标准写法
        • RUN apt-get update && apt-get install -y package-bar package-foo

    例子:

    RUN apt-get update && apt-get install -y \
        aufs-tools \
        automake \
        btrfs-tools \
        build-essential \
        curl \
        dpkg-sig \
        git \
        iptables \
        libapparmor-dev \
        libcap-dev \
        libsqlite3-dev \
        lxc=1.0* \
        mercurial \
        parallel \
        reprepro \
        ruby1.9.1 \
        ruby1.9.1-dev \
        s3cmd=1.1.0*
    • CMD: 推荐使用CMD [“executable”, “param1”, “param2”…]这种格式,CMD [“param”, “param”]则配合ENTRYPOINT使用
    • EXPOSE: Dockerfile 指定要公开的端口,使用docker run时指定映射到宿主机的端口即可
    • ENV: 为了使新的软件更容易运行,可以使用ENV更新PATH变量。如ENV PATH /usr/local/nginx/bin:$PATH确保CMD ["nginx"]即可运行

    ENV也可以这样定义变量:

    ENV PG_MAJOR 9.3
    ENV PG_VERSION 9.3.4
    RUN curl -SL http://example.com/postgres-$PG_VERSION.tar.xz | tar -xJC /usr/src/postgress && …
    ENV PATH /usr/local/postgres-$PG_MAJOR/bin:$PATH
    • ADDorCOPY:ADD比COPY多一些特性「tar 文件自动解包和支持远程 URL」,不推荐添加远程 URL

    如不推荐这种方式:

    ADD http://example.com/big.tar.xz /usr/src/things/
    RUN tar -xJf /usr/src/things/big.tar.xz -C /usr/src/things
    RUN make -C /usr/src/things all

    推荐使用 curl 或者 wget 替换,使用如下方式:

    RUN mkdir -p /usr/src/things \
        && curl -SL http://example.com/big.tar.gz \
        | tar -xJC /usr/src/things \
        && make -C /usr/src/things all

    如果不需要添加 tar 文件,推荐使用COPY。

    参考文档:

    八、容器数据管理

    docker管理数据的方式有两种:

    • 数据卷
    • 数据卷容器

    8.1 数据卷

    数据卷是一个或多个容器专门指定绕过Union File System的目录,为持续性或共享数据提供一些有用的功能:

    • 数据卷可以在容器间共享和重用
    • 数据卷数据改变是直接修改的
    • 数据卷数据改变不会被包括在容器中
    • 数据卷是持续性的,直到没有容器使用它们

    添加一个数据卷

    你可以使用-v选项添加一个数据卷,或者可以使用多次-v选项为一个 docker 容器运行挂载多个数据卷。

    $ sudo docker run --name data -v /data -t -i ubuntu:14.04 /bin/bash # 创建数据卷绑定到到新建容器,新建容器中会创建 /data 数据卷 bash-4.1# ls -ld /data/
    drwxr-xr-x 2 root root 4096 Jul 23 06:59 /data/
    bash-4.1# df -Th
    Filesystem    Type    Size  Used Avail Use% Mounted on
    ... ...
                  ext4     91G  4.6G   82G   6% /data

    创建的数据卷可以通过docker inspect获取宿主机对应路径

    $ sudo docker inspect data
    ... ... "Volumes": { "/data": "/var/lib/docker/vfs/dir/151de401d268226f96d824fdf444e77a4500aed74c495de5980c807a2ffb7ea9" }, # 可以看到创建的数据卷宿主机路径 ... ...

    或者直接指定获取

    $ sudo docker inspect --format="{{ .Volumes }}" data
    map[/data: /var/lib/docker/vfs/dir/151de401d268226f96d824fdf444e77a4500aed74c495de5980c807a2ffb7ea9]

    挂载宿主机目录为一个数据卷

    -v选项除了可以创建卷,也可以挂载当前主机的一个目录到容器中。

    $ sudo docker run --name web -v /source/:/web -t -i ubuntu:14.04 /bin/bash
    bash-4.1# ls -ld /web/
    drwxr-xr-x 2 root root 4096 Jul 23 06:59 /web/
    bash-4.1# df -Th
    ... ...
                  ext4     91G  4.6G   82G   6% /web
    bash-4.1# exit 

    默认挂载卷是可读写的,可以在挂载时指定只读

    $ sudo docker run --rm --name test -v /source/:/test:ro -t -i ubuntu:14.04 /bin/bash

    8.2 创建和挂载一个数据卷容器

    如果你有一些持久性的数据并且想在容器间共享,或者想用在非持久性的容器上,最好的方法是创建一个数据卷容器,然后从此容器上挂载数据。

    创建数据卷容器

    $ sudo docker run -t -i -d -v /test --name test ubuntu:14.04 echo hello

    使用--volumes-from选项在另一个容器中挂载 /test 卷。不管 test 容器是否运行,其它容器都可以挂载该容器数据卷,当然如果只是单独的数据卷是没必要运行容器的。

    $ sudo docker run -t -i -d --volumes-from test --name test1 ubuntu:14.04 /bin/bash

    添加另一个容器

    $ sudo docker run -t -i -d --volumes-from test --name test2 ubuntu:14.04 /bin/bash

    也可以继承其它挂载有 /test 卷的容器

    $ sudo docker run -t -i -d --volumes-from test1 --name test3 ubuntu:14.04 /bin/bash

    非常详细的 Docker 学习笔记

    8.3 备份、恢复或迁移数据卷

    备份

    $ sudo docker run --rm --volumes-from test -v $(pwd):/backup ubuntu:14.04 tar cvf /backup/test.tar /test
    tar: Removing leading `/' from member names
    /test/
    /test/b
    /test/d
    /test/c
    /test/a

    启动一个新的容器并且从test容器中挂载卷,然后挂载当前目录到容器中为 backup,并备份 test 卷中所有的数据为 test.tar,执行完成之后删除容器--rm,此时备份就在当前的目录下,名为test.tar。

    $ ls # 宿主机当前目录下产生了 test 卷的备份文件 test.tar test.tar

    恢复

    你可以恢复给同一个容器或者另外的容器,新建容器并解压备份文件到新的容器数据卷

    $ sudo docker run -t -i -d -v /test --name test4 ubuntu:14.04  /bin/bash $ sudo docker run --rm --volumes-from test4 -v $(pwd):/backup ubuntu:14.04 tar xvf /backup/test.tar -C / # 恢复之前的文件到新建卷中,执行完后自动删除容器 test/ test/b test/d test/c test/a

    8.4 删除 Volumes

    Volume 只有在下列情况下才能被删除:

    • docker rm -v删除容器时添加了-v选项
    • docker run --rm运行容器时添加了--rm选项

    否则,会在/var/lib/docker/vfs/dir目录中遗留很多不明目录。

    参考文档:

    九、链接容器

    docker 允许把多个容器连接在一起,相互交互信息。docker 链接会创建一种容器父子级别的关系,其中父容器可以看到其子容器提供的信息。

    9.1 容器命名

    在创建容器时,如果不指定容器的名字,则默认会自动创建一个名字,这里推荐给容器命名:

    • 1、给容器命名方便记忆,如命名运行 web 应用的容器为 web
    • 2、为 docker 容器提供一个参考,允许方便其他容器调用,如把容器 web 链接到容器 db

    可以通过--name选项给容器自定义命名:

    $ sudo docker run -d -t -i --name test ubuntu:14.04 bash              
    $ sudo docker  inspect --format="{{ .Nmae }}" test
    /test

    注:容器名称必须唯一,即你只能命名一个叫test的容器。如果你想复用容器名,则必须在创建新的容器前通过docker rm删除旧的容器或者创建容器时添加--rm选项。

    9.2 链接容器

    链接允许容器间安全通信,使用--link选项创建链接。

    $ sudo docker run -d --name db training/postgres

    基于 training/postgres 镜像创建一个名为 db 的容器,然后下面创建一个叫做 web 的容器,并且将它与 db 相互连接在一起

    $ sudo docker run -d -P --name web --link db:db training/webapp python app.py

    --link <name or id>:alias选项指定链接到的容器。

    查看 web 容器的链接关系:

    $ sudo docker inspect -f "{{ .HostConfig.Links }}" web
    [/db:/web/db]

    可以看到 web 容器被链接到 db 容器为/web/db,这允许 web 容器访问 db 容器的信息。

    容器之间的链接实际做了什么?一个链接允许一个源容器提供信息访问给一个接收容器。在本例中,web 容器作为一个接收者,允许访问源容器 db 的相关服务信息。Docker 创建了一个安全隧道而不需要对外公开任何端口给外部容器,因此不需要在创建容器的时候添加-p或-P指定对外公开的端口,这也是链接容器的最大好处,本例为 PostgreSQL 数据库。

    Docker 主要通过以下两个方式提供连接信息给接收容器:

    • 环境变量
    • 更新/etc/hosts文件

    环境变量

    当两个容器链接,Docker 会在目标容器上设置一些环境变量,以获取源容器的相关信息。

    首先,Docker 会在每个通过--link选项指定别名的目标容器上设置一个<alias>_NAME环境变量。如果一个名为 web 的容器通过--link db:webdb被链接到一个名为 db 的数据库容器,那么 web 容器上会设置一个环境变量为WEBDB_NAME=/web/webdb.

    以之前的为例,Docker 还会设置端口变量:

    $ sudo docker run --rm --name web2 --link db:db training/webapp env
    . . .
    DB_NAME=/web2/db
    DB_PORT=tcp://172.17.0.5:5432           
    DB_PORT_5432_TCP=tcp://172.17.0.5:5432  # <name>_PORT_<port>_<protocol> 协议可以是 TCP 或 UDP
    DB_PORT_5432_TCP_PROTO=tcp
    DB_PORT_5432_TCP_PORT=5432
    DB_PORT_5432_TCP_ADDR=172.17.0.5
    . . .

    注:这些环境变量只设置给容器中的第一个进程,类似一些守护进程 (如 sshd ) 当他们派生 shells 时会清除这些变量

    更新/etc/hosts文件

    除了环境变量,Docker 会在目标容器上添加相关主机条目到/etc/hosts中,上例中就是 web 容器。

    $ sudo docker run -t -i --rm --link db:db training/webapp /bin/bash
    root@aed84ee21bde:/opt/webapp# cat /etc/hosts
    172.17.0.7  aed84ee21bde
    . . .
    172.17.0.5  db

    /etc/host文件在源容器被重启之后会自动更新 IP 地址,而环境变量中的 IP 地址则不会自动更新的。

    十、构建私有库

    Docker 官方提供了 docker registry 的构建方法 docker-registry

    10.1 快速构建

    快速构建 docker registry 通过以下两步:

    • 安装 docker
    • 运行 registry:docker run -p 5000:5000 registry

    这种方法通过 Docker hub 使用官方镜像 official image from the Docker hub

    10.2 不使用容器构建 registry

    安装必要的软件

    $ sudo apt-get install build-essential python-dev libevent-dev python-pip liblzma-dev

    配置 docker-registry

    sudo pip install docker-registry

    或者 使用 github clone 手动安装

    $ git clone https://github.com/dotcloud/docker-registry.git
    $ cd docker-registry/
    $ cp config/config_sample.yml config/config.yml
    $ mkdir /data/registry -p
    $ pip install .

    运行

    docker-registry

    高级启动方式 [不推荐]

    使用gunicorn控制:

    gunicorn -c contrib/gunicorn_config.py docker_registry.wsgi:application

    或者对外监听开放

    gunicorn --access-logfile - --error-logfile - -k gevent -b 0.0.0.0:5000 -w 4 --max-requests 100 docker_registry.wsgi:application

    10.3 提交指定容器到私有库

    $ docker tag ubuntu:12.04 私有库IP:5000/ubuntu:12.04
    $ docker push 私有库IP:5000/ubuntu

    更多的配置选项推荐阅读官方文档:

    来自: https://blog.csdn.net/zmx729618/article/details/72930474
    展开全文
  • Win10安装Docker详细教程 一、环境准备 1.从Windows菜单栏中打开控制面板 2.控制面板中打开程序 3.选择“启用或关闭Windows功能” 4.打开Hyper-V功能,

    Win10专业版安装Docker详细教程

        Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,
        然后发布到任何流行的 Linux或Windows 机器上,也可以实现虚拟化。
        容器是完全使用沙箱机制,相互之间不会有任何接口。
        Docker官网下载Docker网速较慢,且需要有Docker账号比较麻烦,可以通过以下链接从百盘下载:
        https://download.csdn.net/download/z361406445/11943576
    

    一、环境准备
    1.从Windows菜单栏中打开控制面板
    从Windows菜单栏中打开控制面板
    2.控制面板中打开程序
    在这里插入图片描述
    3.选择“启用或关闭Windows功能”在这里插入图片描述
    4.打开Hyper-V功能,重启电脑。在这里插入图片描述
    注意:
    打开Hyper-V后可能导致与VMware冲突。
    在这里插入图片描述

    5.重启后打开任务管理器,查看虚拟化是否开启成功。在这里插入图片描述
    在这里插入图片描述
    然后开始安装Docker
    在这里插入图片描述
    然后就是点下一步,就不截图了!

    展开全文
  • 目录设置仓库更新apt安装依赖包添加Docker官方 GPG 密钥验证是否拥有带有指纹的密钥设置稳定版仓库安装 Docker Engine-Community(docker-ce)验证是否安装成功注 设置仓库 在新主机上首次安装 Docker Engine-...

    设置仓库

    在新主机上首次安装 Docker Engine-Community 之前,需要设置 Docker 仓库

    更新apt

    $ sudo apt-get update
    

    安装依赖包

    用于通过HTTPS来获取仓库

    $ sudo apt-get install \
        apt-transport-https \
        ca-certificates \
        curl \
        gnupg-agent \
        software-properties-common
    

    添加Docker官方 GPG 密钥

    $ curl -fsSL https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu/gpg | sudo apt-key add -
    

    验证是否拥有带有指纹的密钥

    通过搜索指纹的后8个字符,进行验证

    $ sudo apt-key fingerprint 0EBFCD88
    pub   rsa4096 2017-02-22 [SCEA]
          9DC8 5822 9FC7 DD38 854A  E2D8 8D81 803C 0EBF CD88
    uid           [ unknown] Docker Release (CE deb) <docker@docker.com>
    sub   rsa4096 2017-02-22 [S]
    

    设置稳定版仓库

    $ sudo add-apt-repository \
       "deb [arch=amd64] https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu/ \
      $(lsb_release -cs) \
      stable"
    

    安装 Docker Engine-Community(docker-ce)

    安装最新版本的 Docker Engine-Community 和 containerd

    $ sudo apt-get install docker-ce docker-ce-cli containerd.io
    

    验证是否安装成功

    service docker status
    

    通过以上方式安装完毕后可以找到docker.service文件,如果通过其他方式,可能会出现能够正常使用docker,但是找不到service文件的问题!

    展开全文
  • Docker详细教程和总结

    2020-06-25 10:09:22
    超长文警告!...Docker 安装Docker 的基本组成Docker 安装步骤配置阿里云镜像加速HelloWorld启动流程分析底层原理Docker 常用命令帮助命令镜像命令docker images 查看所有本地主机上的镜像docker search 搜

    超长文警告!!!建议先看目录

    docker入门及相关案例 带你了解docker
    总结不易,赞同的话请点个赞哦~
    如有错误,欢迎指正!

    最后更新时间  ===2020 06 17===


    Docker 概述

    Docker 为什么会出现?

    1. 在一款产品/项目的开发过程中,要经历 【开发 ==> 上线】 这样的一个过程,就会有两套环境(dev prod),例如:应用环境和应用配置
    2. 一般公司也会配有两个部门(开发、运维),环境问题就会导致项目出现问题,有句话是这么说的:【明明在我的电脑就可以运行,为什么你的就不行】。这也能看出项目的运行有对环境的要求了,有可能是因为版本不同,导致服务不可用,也有可能是其他的原因。
    3. 那解决方案就是,要么运维来管理开发,统一环境;要么开发把运维的活也包了,不然工资也不会这么高。
    4. 那么这里面最根本的就是环境问题,其中环境配置就是比较麻烦的,特别是在搭建集群环境时,要一台一台机器去配置环境,费时费力。
    5. 以往我们发布项目的时候有jar包/war包,假设我们能够带着环境来上线项目,就会方便很多。
    6. 特别是在Windows上开发,Linux上发布,这样跨平台的环境配置,十分麻烦
    7. 那么相比于传统的【开发人员给jar包 运维来上线】 ,现在更倾向于 【开发打包部署上线一套流程】就能解决。
    8. 这就诞生了Docker,为以上的问题提出了一套解决方案
    9. 【java开发出jar包】--->【带上环境打包项目(镜像)】--->【发布到Docker仓库】--->【下载镜像,直接运行】

    Docker 简介

    官网首页https://www.docker.com/
    官方文档https://docs.docker.com/
    Docker镜像仓库地址https://hub.docker.com/
    在这里插入图片描述

    来自百度百科

    1. Docker 是 PaaS 提供商 【dotCloud】 开源的一个基于 LXC 的高级容器引擎,源代码托管在 Github 上, 基于go语言并遵从 Apache2.0 协议开源。
    2. Docker 的思想就来自于【集装箱】,这个可以从logo中看出来,在码头上集装箱会将货物【隔离】开,类似于在电脑上跑了很多应用,原来可能应用之间会发生冲突,例如:JRE上会跑很多Java应用,可能会发生端口冲突,在原来都是交叉的,现在就要将他们隔离开来
    3. 隔离,也是Docker的核心思想!将应用打包装箱,每个箱子互相隔离!另外,Docker也可以通过隔离机制,将服务器的性能发挥到极致。就好比在集群环境中,以往要开多台虚拟机,现在只需要一台虚拟机,然后利用Docker的隔离机制,跑多个应用,模拟集群环境。

    Docker 的历史

    【了解技术的历史才能更好的学习技术】

    • 【2010年】,有几个搞IT的年轻人,在美国成立了一家公司:dotCloud,做一些 PaaS 的云计算服务!说白了就是 LXC 有关的容器技术。
    • 他们就将自己的容器化技术进行统一的命名,称为Docker
    • Docker 刚刚诞生的时候,没有引起行业的注意,难以维持
    • 于是打算将技术开源,将源代码开放
    • 【2013年】 公司创始人 Solomon Hykes 将Docker开源,于是一下火爆了起来,Docker每个月都会更新一个版本
    • 【2014年4月9日】,Docker 1.0发布
    • Docker的优点
      • 十分的轻巧!在容器技术出来之前,使用的都是虚拟机技术(通过软件模拟出一台或多台电脑),但是虚拟机特别占内存,浪费性能
      • 虚拟机也是虚拟化技术,Docker的容器技术,也是一种虚拟化技术!本质是差不多的。
      • 两者区别
        • 虚拟机时下载原生镜像,然后安装,要实现隔离只能开启多个虚拟机
        • docker的隔离是通过【镜像机制】,不是完整的电脑,只是最核心的环境,十分的轻巧,再加上需要的环境,打包成镜像,运行的时候运行镜像即可,十分小巧
        • 虚拟机要运行的话需要几个G,而Docker镜像只需要几M或几百M;而且几乎是秒级启动
    • 至今已经发展成所有开发人员必须要会的技术

    Docker 能干什么?

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IbbXr6dv-1593050117053)(D:/typora/Typora/img/Docker 2020最新版 超详细/1592643101078.png)]

    一台电脑中需要有内核、依赖库,在这个基础上再运行应用

    虚拟机技术就是在电脑上再模拟出一台计算机

    虚拟机技术的缺点

    1. 资源占用十分多
    2. 冗余步骤多
    3. 启动很慢

    容器化技术
    在这里插入图片描述

    1. 容器化技术不是模拟出一个完整的操作系统
    2. 每一个容器都会包含依赖库环境和应用,而且每个容器之间互相隔离,不同于传统的虚拟机技术,各个应用交叉共用依赖库,容易发生冲突

    比起 Docker 和虚拟机技术的不同

    • 传统虚拟机:虚拟出一套硬件,运行一个完整的操作系统,然后在这个系统上安装和运行环境
    • 容器内的应用直接运行在宿主机的内核,容器时没有自己的内核的,也没有虚拟硬件,所以就轻便了
    • 每个容器之间是互相隔离的,每个容器内都有一个属于自己的文件系统,互不影响

    使用了Docker之后,我们部署应用就和搭积木一样

    • 应用更快速的交付和部署
      传统:一堆帮助文档,安装程序
      Docker: 打包镜像发布测试,一键运行
    • 更便捷的升级和扩缩容
      项目打包为一个镜像,如果服务器A上运行出现性能瓶颈,需要进行水平扩展,可以直接在服务器B上一键运行这个镜像
    • 更简单的系统运维
      在容器化之后,开发、测试的环境都是高度一致的
    • 更高效的计算资源利用
      Docker是内核级别的虚拟化,可以在一个物理机上运行很多的容器实例,将服务器的性能发挥到极致

    Docker 安装

    Docker 的基本组成

    在这里插入图片描述
    在这里插入图片描述

    镜像(image)

    就好比是一个模板,可以通过这个模板来创建多个容器。如tomcat镜像==>run=>tomcat容器(提供服务器),通过这个镜像可以创建多个容器。【最终服务运行或者项目运行就是在容器中】

    容器(container)
    Docker利用容器技术,独立运行一个或一个组应用,通过镜像来创建的
    有启动、停止、删除等基本命令
    目前就可以把这个容器理解为一个简易的Linux系统

    仓库(repository)
    仓库就是存放镜像的地方!
    仓库分为【公有仓库】和【私有仓库】

    Docker 安装步骤

    1. 环境准备:CentOS7 虚拟机【可以在虚拟机上,也可以在远程终端上,例如XShell / FinalShell】
    2. 环境查看
    uname -r // 查看系统内核
    cat /etc/os-release  // 查看系统基本信息
    docker -v  //查看docker版本
    docker stats //查看docker的cpu状态
    docker top 容器id //查看docker的进程信息
    
    1. 安装
      查看官网帮助文档 https://docs.docker.com/engine/install/

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pyy5OmB8-1593050117100)(D:/typora/Typora/img/Docker 2020最新版 超详细/1592643179017.png)]

    )(D:/typora/Typora/img/Docker 2020最新版 超详细/1592643192083.png)]

    docker安装的操作按照以下步骤即可

    # 1. 卸载旧的版本
    	yum remove docker \
            docker-client \
            docker-client-latest \
            docker-common \
            docker-latest \
            docker-latest-logrotate \
            docker-logrotate \
            docker-engine
    
    # 2. 需要的安装包
    yum install -y yum-utils
    
    # 3. 设置镜像仓库 这里默认是国外的,我们最好用国内的 推荐使用阿里云
        yum-config-manager \
        --add-repo \
        http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
        # https://download.docker.com/linux/centos/docker-ce.repo
        
    
    # 4. 文档上接下来的是一些配置【Optional: Enable the nightly or test repositories.】
    #    没有什么用,这里就暂时不配置了
    
    # 5. 安装docker相关的内容 docker-ce是社区版  ee是企业版 推荐使用ce 
    # --》  在安装之前最好先更新一下yum软件包索引,命令-> yum makecache fast
    yum install docker-ce docker-ce-cli containerd.io
    # 这里也可以指定版本安装,帮助文档的第二点就是安装的方法,先查看版本列表,再使用命令指定版本安装
    
    # 6. 启动Docker
    service docker start
    #systemctl start docker
    
    # 7. 查看是否启动成功
    docker version    # 查看docker版本
    
    # 8. 启动hello-world
    docker run hello-world
    
    # 9. 卸载docker 了解即可 两个步骤【卸载依赖 删除目录】
    yum remove docker-ce docker-ce-cli containerd.io
    rm -rf /var/lib/docker
    
    # 10.升级docker引擎 可以下载更新的软件包文件然后再重复一遍安装步骤
    # 然后使用 yum -y upgrade 代替 yum -y install  并指向新文件
    
    # docker设置开机自启动
    systemctl enable docker
    

    配置阿里云镜像加速

    链接地址:https://cr.console.aliyun.com/cn-shanghai/instances/repositories

    在这里插入图片描述

    在这里插入图片描述

    sudo mkdir -p /etc/docker
    
    sudo tee /etc/docker/daemon.json <<-'EOF'
    {
      "registry-mirrors": ["https://sxsbhw9e.mirror.aliyuncs.com"]
    }
    EOF
    
    sudo systemctl daemon-reload
    
    sudo systemctl restart docker
    

    根据镜像加速器中的4条命令执行就可以

    HelloWorld启动流程分析

    在这里插入图片描述
    在这里插入图片描述

    底层原理

    Docker 是怎么工作的?

    Docker 是一个Client · Server 结构的系统,Docker的守护进程(Docker daemon)运行在主机上,通过Socket从客户端访问!

    Docker Server 接收到 Docker Client 的指令,就会执行这个命令

    在这里插入图片描述

    Docker 为什么比虚拟机快?

    1、Docker 有着比虚拟机更少的抽象层
    2、Docker 利用的是宿主机的内核,VM 需要的是GuestOS【就是需要再搭建一个系统环境】
    在这里插入图片描述

    所以说,新建一个容器的时候,Docker 不需要像虚拟机那样重新加载一个操作系统的内核,避免一些引导性的操作;而虚拟机是加载 Guest OS,是分钟级别的,Docker 是利用宿主机的操作系统,省略了这个复杂的过程,所以是秒级的启动

    在这里插入图片描述

    如果看着还不是很懂,没关系,接着往下看,当你学习完所有的命令之后再回来看这段理论,就会清晰许多。


    Docker 常用命令

    帮助命令

    docker version       # 显示docker版本信息
    docker info          # docker的系统信息,包括镜像和容器的数量
    docker 命令 --help   # 帮助命令
    

    如果碰到不知道的可查看帮助文档:【https://docs.docker.com/engine/reference/commandline/build/

    镜像命令

    docker images 查看所有本地主机上的镜像

    官方文档

    # 查看帮助 其他命令的用法类似 
    [root@iZwz98zprwjrt7d2pp9g0zZ ~]# docker images --help
    
    Usage:  docker images [OPTIONS] [REPOSITORY[:TAG]]
    
    List images
    
    Options:
      -a, --all             列出所有镜像
          --digests         显示摘要
      -f, --filter filter   根据提供的条件过滤输出
          --format string   指定返回值的模板文件
          --no-trunc        不截断输出,即显示完整的镜像信息
      -q, --quiet           只显示镜像ID
    # 比较常用的是 -a -q
    
    
    # 查看本地主机上的镜像
    [root@admin ~]# docker images
    REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
    hello-world         latest              bf756fb1ae65        5 months ago        13.3kB
    # 解释
    REPOSITORY   镜像的仓库源
    TAG          镜像的标签
    IMAGE ID     镜像的id
    CREATED      镜像的创建时间
    SIZE         镜像的大小
    

    docker search 搜索镜像

    网页版可以通过 Docker Hub 搜索镜像,在Linux命令行里用 docker search搜索

    在这里插入图片描述

    [root@admin~]# docker search mysql
    NAME                              DESCRIPTION                                     STARS               OFFICIAL            AUTOMA
    TED
    mysql                             MySQL is a widely used, open-source relation…   9621                [OK]                
    mariadb                           MariaDB is a community-developed fork of MyS…   3495                [OK]                
    # 可选项,通过收藏或其他来过滤检索结果
    --filter=stars=3000  # 搜索出来的镜像就是STARS大于5000的
    [root@admin~]# docker search mysql --filter=stars=5000
    NAME                DESCRIPTION                                     STARS               OFFICIAL            AUTOMATED
    mysql               MySQL is a widely used, open-source relation…   9621                [OK]                
    

    docker pull 下载镜像

    在这里插入图片描述

    # 下载镜像 docker pull 镜像名[:tag]  tag可以指定版本,没有的话默认使用最新版
    [root@admin ~]# docker pull mysql
    Using default tag: latest   # 如果不写tag 默认就是最新版
    latest: Pulling from library/mysql  
    8559a31e96f4: Pull complete    # 分层下载,docker image 的核心,联合文件系统
    d51ce1c2e575: Pull complete 
    c2344adc4858: Pull complete 
    fcf3ceff18fc: Pull complete 
    16da0c38dc5b: Pull complete 
    b905d1797e97: Pull complete 
    4b50d1c6b05c: Pull complete 
    c75914a65ca2: Pull complete 
    1ae8042bdd09: Pull complete 
    453ac13c00a3: Pull complete 
    9e680cd72f08: Pull complete 
    a6b5dc864b6c: Pull complete 
    Digest: sha256:8b7b328a7ff6de46ef96bcf83af048cb00a1c86282bfca0cb119c84568b4caf6  # 签名信息
    Status: Downloaded newer image for mysql:latest
    docker.io/library/mysql:latest  # 真实地址 
    # 即:docker pull mysql 和 docker pull docker.io/library/mysql:latest 是等价的
    
    # 指定版本下载 版本不可乱写 可在 docker hub 上查看
    [root@admin ~]# docker pull mysql:5.7  # 加上了tag标签后可指定版本下载
    5.7: Pulling from library/mysql
    8559a31e96f4: Already exists   # 可以看到这里会显示一些文件已存在
    d51ce1c2e575: Already exists   # 这就是分层下载的好处 可以共用一些文件
    c2344adc4858: Already exists 
    fcf3ceff18fc: Already exists 
    16da0c38dc5b: Already exists 
    b905d1797e97: Already exists 
    4b50d1c6b05c: Already exists 
    d85174a87144: Pull complete 
    a4ad33703fa8: Pull complete 
    f7a5433ce20d: Pull complete 
    3dcd2a278b4a: Pull complete 
    Digest: sha256:32f9d9a069f7a735e28fd44ea944d53c61f990ba71460c5c183e610854ca4854
    Status: Downloaded newer image for mysql:5.7
    docker.io/library/mysql:5.7
    
    # 下载完成后查看镜像
    [root@admin ~]# docker images
    REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
    mysql               5.7                 9cfcce23593a        4 days ago          448MB
    mysql               latest              be0dbf01a0f3        4 days ago          541MB
    hello-world         latest              bf756fb1ae65        5 months ago        13.3kB
    

    docker rmi 删除镜像

    可以通过IMAGE ID删除,也可以根据镜像名称来删除

    # 删除指定id的镜像
    docker rmi -f 容器id  
    # 删除多个镜像
    docker rmi -f 容器id 容器id 容器id 
    # 删除全部镜像
    docker rmi -f $(docker images -aq)
    

    容器命令

    【说明】有了镜像才可以创建容器,要先下载一个centos镜像来测试学习

     docker pull centos
    

    docker run 启动容器

    docker run [可选参数] image
    
    # 常用参数说明
    --name="NAME"  容器名字 用于区分容器
    -d             后台方式运行
    -it            使用交互方式运行,例如要进入容器查看内容
    -p             指定容器端口 -p 8080
    	-p ip:主机端口:容器端口
    	-p 主机端口:容器端口 (常用)
    	-p 容器端口
    	容器端口    (直接写容器端口也行)
    -P             大写的P 随机指定端口
    
    # 测试 启动并进入新建容器
    # 以交互模式启动 centos 并进入容器 同时指定使用 centos 里面的 bash 作为控制台进行交互
    [root@admin ~]# docker run -it centos /bin/bash
    # 这里可以看到命令行的前缀发生了变化 表示已经进入容器了
    [root@67d60e7e973b /]# ls
    bin  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
    
    # 退出容器到主机
    [root@67d60e7e973b /]# exit
    exit
    [root@admin ~]# ls
    mysql80-community-release-el7-3.noarch.rpm  shell
    

    docker ps 查看正在运行的容器

    -a    # 列出当前正在运行的容器 + 历史运行过的容器 就是全部容器
    -n=?  # 显示最近创建的容器 ?表示个数
    -q    # 只显示容器的编号
    
    [root@admin ~]# docker ps
    CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
    
    [root@admin ~]# docker ps -a
    CONTAINER ID        IMAGE               COMMAND             CREATED              STATUS                          PORTS               NAMES
    67d60e7e973b        centos              "/bin/bash"         15 minutes ago       Exited (0) 15 minutes ago                           keen_yalow
    95b5db0ebd50        hello-world         "/hello"            4 hours ago          Exited (0) 4 hours ago                              wizardly_leavitt
    
    [root@admin ~]# docker ps -aq     
    

    退出容器

    exit    # 直接停止容器并退出
    
    ctrl + p + q  # 直接按快捷键 容器不停止退出
    
    #不停止退出再次启动的两种方式
    docker exec -it 容器id /bin/bash
    docker attach 容器id	
    

    docker rm 删除容器

    docker rm 容器id                 # 删除指定id的容器,不能删除正在运行的容器 rm -f 强制删除
    docker rm -f $(docker ps -aq)    # 删除所有容器
    docker ps -a -q|xargs docker rm  # 通过管道删除所有的容器
    

    启动和停止容器

    docker start 容器id      # 启动容器
    docker restart 容器id    # 重启容器
    docker stop 容器id       # 停止容器
    docker kill 容器id       # 杀死容器
    

    常用其他命令

    docker run -d 后台启动容器

    # docker run id 镜像名 后台启动
    docker run -d  centos   # 后台启动
    
    # 启动docker后ps 会发现centos停止了
    # 常见的坑:docker 容器使用后台运行,就必须要有一个前台进程(就是交互)
    # 如果 docker 发现没有应用,自己没有提供服务,就会立刻停止
    

    docker logs 查看日志

    docker logs -f -t --tail 容器id   # 查看容器运行日志
    
    # 举例 在容器内运行脚本 while循环输出字符串
    # 编写脚本
    [root@admin ~]# docker run -d centos /bin/sh -c "while true;do echo hello;sleep 1;done"            
    c482e0df32230d949c36dd9047f93257c23702960298317830f1b8b2ad42e28c
    
    # 查看容器
    [root@admin ~]# docker ps -a
    CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
    c482e0df3223        centos              "/bin/sh -c 'while t…"   11 seconds ago      Up 10 seconds                           ecstatic_dhawan
    
    # 显示日志 展示10条  两种方法
    [root@admin ~]# docker logs -tf --tail 10 容器id ||  docker logs -f --tail 10 -t 014e  2020-06-13T08:04:41.312351474Z hello
    2020-06-13T08:04:42.314853838Z hello
    2020-06-13T08:04:43.317313743Z hello
    2020-06-13T08:04:44.319772893Z hello
    2020-06-13T08:04:45.322357813Z hello
    2020-06-13T08:04:46.324866999Z hello
    2020-06-13T08:04:47.327293107Z hello
    2020-06-13T08:04:47.327293107Z hello
    2020-06-13T08:04:47.327293107Z hello
    2020-06-13T08:04:47.327293107Z hello
    ...(直接输出10条日志后 后面还会继续增加 因为while循环一直在输出)
    # 不加 --tail 10 就是显示全部日志
    

    docker top 查看容器中进程信息

    # 查看容器内的进程信息
    docker top 容器id 
    

    docker inspect 查看镜像的元数据(重要)

    # 查看容器内所有信息
    docker inspect 容器id
    # 测试
    [root@admin ~]# docker inspect 09b2534befb1
    [
        {
            # 容器id 能发现命令中的id只是这里面的一小部分
            "Id": "09b2534befb12a8c5297bbc4cbe26ae3b528478d713efbb23e7c5cdaf8400b26",、
            # 创建时间
            "Created": "2020-06-13T08:12:31.964868162Z",
            # 交互前台路径
            "Path": "/bin/bash",
            # 携带参数
            "Args": [],
            # 容器状态
            "State": {
                "Status": "running",
                "Running": true,
                "Paused": false,
                "Restarting": false,
                "OOMKilled": false,
                "Dead": false,
                "Pid": 2076,
                "ExitCode": 0,
                "Error": "",
                "StartedAt": "2020-06-13T08:12:32.29364097Z",
                "FinishedAt": "0001-01-01T00:00:00Z"
            },
            # 镜像来源
            "Image": "sha256:470671670cac686c7cf0081e0b37da2e9f4f768ddc5f6a26102ccd1c6954c1ee",
            "ResolvConfPath": "/var/lib/docker/containers/09b2534befb12a8c5297bbc4cbe26ae3b528478d713efbb23e7c5cdaf8400b26/resolv.conf",
            "HostnamePath": "/var/lib/docker/containers/09b2534befb12a8c5297bbc4cbe26ae3b528478d713efbb23e7c5cdaf8400b26/hostname",
            "HostsPath": "/var/lib/docker/containers/09b2534befb12a8c5297bbc4cbe26ae3b528478d713efbb23e7c5cdaf8400b26/hosts",
            "LogPath": "/var/lib/docker/containers/09b2534befb12a8c5297bbc4cbe26ae3b528478d713efbb23e7c5cdaf8400b26/09b2534befb12a8c5297bbc4cbe26ae3b528478d713efbb23e7c5cdaf8400b26-json.log",
            "Name": "/compassionate_kepler",
            "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": "no",
                    "MaximumRetryCount": 0
                },
                "AutoRemove": false,
                "VolumeDriver": "",
                "VolumesFrom": null,
                "CapAdd": null,
                "CapDrop": null,
                "Capabilities": null,
                "Dns": [],
                "DnsOptions": [],
                "DnsSearch": [],
                "ExtraHosts": null,
                "GroupAdd": null,
                "IpcMode": "private",
                "Cgroup": "",
                "Links": null,
                "OomScoreAdj": 0,
                "PidMode": "",
                "Privileged": false,
                "PublishAllPorts": false,
                "ReadonlyRootfs": false,
                "SecurityOpt": null,
                "UTSMode": "",
                "UsernsMode": "",
                "ShmSize": 67108864,
                "Runtime": "runc",
                "ConsoleSize": [
                    0,
                    0
                ],
                "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,
                "DeviceRequests": null,
                "KernelMemory": 0,
                "KernelMemoryTCP": 0,
                "MemoryReservation": 0,
                "MemorySwap": 0,
                "MemorySwappiness": null,
                "OomKillDisable": false,
                "PidsLimit": null,
                "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/9d1b03a32ce30afcaf3da85e14de8412cad304c4e4815a6ff045883017a2e4ae-init/diff:/var/lib/docker/overlay2/5108dfc3feeecdef61ca695a9c4b8c459eb743214117505341369d6c7f62fe53/diff",
                    "MergedDir": "/var/lib/docker/overlay2/9d1b03a32ce30afcaf3da85e14de8412cad304c4e4815a6ff045883017a2e4ae/merged",
                    "UpperDir": "/var/lib/docker/overlay2/9d1b03a32ce30afcaf3da85e14de8412cad304c4e4815a6ff045883017a2e4ae/diff",
                    "WorkDir": "/var/lib/docker/overlay2/9d1b03a32ce30afcaf3da85e14de8412cad304c4e4815a6ff045883017a2e4ae/work"
                },
                "Name": "overlay2"
            },
            # 挂载信息
            "Mounts": [],
            # 基本配置
            "Config": {
                "Hostname": "09b2534befb1",
                "Domainname": "",
                "User": "",
                "AttachStdin": true,
                "AttachStdout": true,
                "AttachStderr": true,
                "Tty": true,
                "OpenStdin": true,
                "StdinOnce": true,
                # 环境变量 没有java的所以用不了java
                "Env": [
                    "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
                ],
                # 命令行
                "Cmd": [
                    "/bin/bash"
                ],
                "Image": "centos",
                "Volumes": null,
                "WorkingDir": "",
                "Entrypoint": null,
                "OnBuild": null,
                "Labels": {
                    "org.label-schema.build-date": "20200114",
                    "org.label-schema.license": "GPLv2",
                    "org.label-schema.name": "CentOS Base Image",
                    "org.label-schema.schema-version": "1.0",
                    "org.label-schema.vendor": "CentOS",
                    "org.opencontainers.image.created": "2020-01-14 00:00:00-08:00",
                    "org.opencontainers.image.licenses": "GPL-2.0-only",
                    "org.opencontainers.image.title": "CentOS Base Image",
                    "org.opencontainers.image.vendor": "CentOS"
                }
            },
            # 网络设置
            "NetworkSettings": {
                "Bridge": "",
                "SandboxID": "26ea3297b66bbae1ac7798d19783e51fcc1f88037409888db0137bf3549b18d3",
                "HairpinMode": false,
                "LinkLocalIPv6Address": "",
                "LinkLocalIPv6PrefixLen": 0,
                "Ports": {},
                "SandboxKey": "/var/run/docker/netns/26ea3297b66b",
                "SecondaryIPAddresses": null,
                "SecondaryIPv6Addresses": null,
                "EndpointID": "25b52bae99d2c591b03ba97e644dc3b3a26917209523d76bb78f3190b364a3a3",
                "Gateway": "172.17.0.1",
                "GlobalIPv6Address": "",
                "GlobalIPv6PrefixLen": 0,
                "IPAddress": "172.17.0.2",
                "IPPrefixLen": 16,
                "IPv6Gateway": "",
                "MacAddress": "02:42:ac:11:00:02",
                "Networks": {
                	# 现在使用的网络工作模式 桥接模式
                    "bridge": {
                        "IPAMConfig": null,
                        "Links": null,
                        "Aliases": null,
                        "NetworkID": "695424c9542cb18c12700a9df49559009382acf4ace4668dafc94367620a0522",
                        "EndpointID": "25b52bae99d2c591b03ba97e644dc3b3a26917209523d76bb78f3190b364a3a3",
                        "Gateway": "172.17.0.1",
                        "IPAddress": "172.17.0.2",
                        "IPPrefixLen": 16,
                        "IPv6Gateway": "",
                        "GlobalIPv6Address": "",
                        "GlobalIPv6PrefixLen": 0,
                        "MacAddress": "02:42:ac:11:00:02",
                        "DriverOpts": null
                    }
                }
            }
        }
    ]
    

    docker exec/attach 进入当前正在运行的容器

    # 我们通常都是将容器放在后台运行,有时候就需要进入容器,修改一些配置
    
    # 方式1
    docker exec -it 容器id bashShell的形式
    # 测试
    [root@admin ~]# docker ps -a
    CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
    09b2534befb1        centos              "/bin/bash"         11 minutes ago      Up 11 minutes                           compassionate_kepler
    [root@admin ~]# docker exec -it 09b2534befb1 /bin/bash
    [root@09b2534befb1 /]# ps -ef
    UID        PID  PPID  C STIME TTY          TIME CMD
    root         1     0  0 08:12 pts/0    00:00:00 /bin/bash
    root        15     0  0 08:24 pts/1    00:00:00 /bin/bash
    root        28    15  0 08:24 pts/1    00:00:00 ps -ef
    
    # 方式2
    docker attach 容器id
    # 测试
    [root@admin ~]# docker ps -a
    CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
    09b2534befb1        centos              "/bin/bash"         13 minutes ago      Up 13 minutes                           compassionate_kepler
    [root@admin ~]# docker attach 09b2534befb1
    [root@09b2534befb1 /]# 
    
    两种命令的区别:
    1、docker exec   是进入容器后【开启了一个新的终端】,可以在里面操作
    2、docker attach 是进入容器【正在执行的终端】,不会启动新的进程
    

    docker cp 从容器内拷贝文件到主机上

    # 命令
    docker cp 容器id:容器内路径 目的主机路径
    # 测试
    # 在容器内新建文件
    [root@09b2534befb1 /]# cd /home
    [root@09b2534befb1 home]# ls
    [root@09b2534befb1 home]# touch hello.txt
    # 拷贝文件可退出容器拷贝,即使停止了数据依然在
    [root@09b2534befb1 home]# exit
    exit
    [root@admin ~]# docker ps
    CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
    # 拷贝数据到主机的home目录下
    [root@admin ~]# docker cp 09b2534befb1:/home/hello.txt /home
    [root@admin ~]# cd /home
    # 查看文件
    [root@admin home]# ls
    hello.txt  study
    
    # 拷贝是一个手动过程,之后我们可以使用 -v 卷的技术,自动同步
    

    要将所有命令全部敲一遍哦,这样才能加深印象

    docker常用命令

    #查看镜像
    docker images 
    
    docker rmi -f 容器id  		      # 删除指定id的镜像
    docker rmi -f 容器id 容器id    	    # 删除多个镜像
    docker rmi -f $(docker images -aq) # 删除全部镜像
    
    docker ps     #查看正在运行的容器
    docker ps-a   #查看所有容器
    docker ps-aq  #查看所有容器编号
    
    docker run -it centos /bin/bash   #开启centos镜像的容器 
    ctrl + p + q  # 直接按快捷键容器不停止退出
    docker exec -it 容器id /bin/bash    #进入当前正在运行的容器1
    docker attach 容器id				  #进入当前正在运行的容器2
    
    exit / ctrl+c  	#退出当前容器
    
    docker start 容器id      # 启动容器
    docker stop 容器id      #停止当前容器运行
    docker kill 容器id        #杀死容器
    
    docker rm 容器id                  # 删除指定id的容器,rm -f 强制删除
    docker rm -f $(docker ps -aq)    # 删除所有容器
    
    docker logs 容器id               #查看日志
    
    docker cp 容器id:/home/xx文件 linux的目录  #拷贝文件
    

    命令小结

    官方命令图谱

    Docker 的命令是十分多的,上面我们学习的那些都是最常用的容器和镜像的命令

      attach      Attach local standard input, output, and error streams to a running container    # 当前 shell 下 attach 连接指定运行镜像
      build       Build an image from a Dockerfile                                                 # 通过 Dokcerfile 定制镜像
      commit      Create a new image from a container's changes                                    # 提交当前容器为新的镜像
      cp          Copy files/folders between a container and the local filesystem                  # 从容器中拷贝指定文件或目录到宿主机中
      create      Create a new container                                                           # 创建一个新的容器,同 run 但是不启动容器
      diff        Inspect changes to files or directories on a container's filesystem              # 查看 Docker 容器变化
      events      Get real time events from the server                                             # 从 Docker 服务获取容器实时时间
      exec        Run a command in a running container                                             # 在已存在的容器上运行命令
      export      Export a container's filesystem as a tar archive                                 # 到处容器的内容流作为一个 tar 归档文件(对应 import)
      history     Show the history of an image                                                     # 显示镜像形成历史
      images      List images                                                                      # 列出系统当前镜像
      import      Import the contents from a tarball to create a filesystem image                  # 从 tar 包中的内容创建一个新的文件系统映像(对应 export)
      info        Display system-wide information                                                  # 显示系统相关信息
      inspect     Return low-level information on Docker objects                                   # 查看容器详细信息
      kill        Kill one or more running containers                                              # kill 指定 docker 容器
      load        Load an image from a tar archive or STDIN                                        # 从一个 tar 包中加载镜像(对应 save)
      login       Log in to a Docker registry                                                      # 注册或登录一个 docker 源服务器
      logout      Log out from a Docker registry                                                   # 从当前 Docker registry 退出
      logs        Fetch the logs of a container                                                    # 输出当前容器日志信息
      pause       Pause all processes within one or more containers                                # 暂停容器
      port        List port mappings or a specific mapping for the container                       # 查看映射端口对应的容器内部源端口
      ps          List containers                                                                  # 列出容器列表
      pull        Pull an image or a repository from a registry                                    # 从 docker 镜像源服务器拉去指定镜像或者库镜像
      push        Push an image or a repository to a registry                                      # 推送指定镜像或者库镜像至 docker 源服务器
      rename      Rename a container                                                               # 重命名一个容器
      restart     Restart one or more containers                                                   # 重启一个或多个容器
      rm          Remove one or more containers                                                    # 移除一个或多个容器
      rmi         Remove one or more images                                                        # 移除一个或多个镜像(无容器使用该镜像才可移除,否则需删除相关容器才可继续或 -f 强制执行)
      run         Run a command in a new container                                                 # 创建一个新的容器并运行一个命令
      save        Save one or more images to a tar archive (streamed to STDOUT by default)         # 保存一个镜像为一个 tar 包(对应load)
      search      Search the Docker Hub for images                                                 # 在 docker hub 中搜索镜像
      start       Start one or more stopped containers                                             # 启动容器
      stats       Display a live stream of container(s) resource usage statistics                  # 显示实时的容器资源使用情况统计流
      stop        Stop one or more running containers                                              # 停止容器
      tag         Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE                            # 给源中的镜像打标签
      top         Display the running processes of a container                                     # 查看容器中运行的进程信息
      unpause     Unpause all processes within one or more containers                              # 取消暂停容器
      update      Update configuration of one or more containers                                   # 为容器更新配置
      version     Show the Docker version information                                              # 查看 docker 版本号
      wait        Block until one or more containers stop, then print their exit codes             # 阻塞直到一个或多个容器停止,然后打印其退出代码,即截取容器停止时的退出状态值
    

    实战练习

    作业1、使用 Docker 安装 Nginx (学习暴露端口)

    1、 搜索镜像 search
    [root@admin ~]# docker search --filter=stars=8000 nginx
    NAME                DESCRIPTION                STARS               OFFICIAL            AUTOMATED
    nginx               Official build of Nginx.   13326               [OK]                
    2、 下载镜像 pull
    [root@admin ~]# docker pull nginx
    Using default tag: latest
    latest: Pulling from library/nginx
    8559a31e96f4: Pull complete 
    8d69e59170f7: Pull complete 
    3f9f1ec1d262: Pull complete 
    d1f5ff4f210d: Pull complete 
    1e22bfa8652e: Pull complete 
    Digest: sha256:21f32f6c08406306d822a0e6e8b7dc81f53f336570e852e25fbe1e3e3d0d0133
    Status: Downloaded newer image for nginx:latest
    docker.io/library/nginx:latest
    
    3、 查看镜像 images
    [root@admin ~]# docker images
    REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
    nginx               latest              2622e6cca7eb        3 days ago          132MB
    centos              latest              470671670cac        4 months ago        237MB
    hello-world         latest              bf756fb1ae65        5 months ago        13.3kB
    
    4、 启动 run  -d 后台运行  -p 指定端口 -name为自定义的名 主机的3344映射到容器的80端口
    [root@admin ~]# docker run -d --name nginx01 -p 3344:80 nginx
    129642f969d4cff63d173ba822c096192a435830f64a6ffe77e8d6743f342767
    
    5、 查看启动 ps
    [root@admin ~]# docker ps
    CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                  NAMES
    129642f969d4        nginx               "/docker-entrypoint.…"   4 seconds ago       Up 4 seconds        0.0.0.0:3344->80/tcp   nginx01
    
    6、 运行测试nginx
    [root@admin ~]# curl localhost:3344
    <!DOCTYPE html>
    <html>
    <head>
    <title>Welcome to nginx!</title>
    <style>
        body {
            width: 35em;
            margin: 0 auto;
            font-family: Tahoma, Verdana, Arial, sans-serif;
        }
    </style>
    </head>
    <body>
    <h1>Welcome to nginx!</h1>
    <p>If you see this page, the nginx web server is successfully installed and
    working. Further configuration is required.</p>
    
    <p>For online documentation and support please refer to
    <a href="http://nginx.org/">nginx.org</a>.<br/>
    Commercial support is available at
    <a href="http://nginx.com/">nginx.com</a>.</p>
    
    <p><em>Thank you for using nginx.</em></p>
    </body>
    </html>
    
    至此,nginx安装完成。如使用阿里云服务器,且在安全组配置中配置了3344端口,就可直接打开nginx的页面
    如访问:39.106.230.179:3344 就可看到 Welcome to nginx! 页面
    
    
    #根据名称进入相关的nginx容器
    docker exec -it nginx01 /bin/bash
    
    #查看nginx包含的文件
    whereis nginx
    
    #查看到nginx的配置
    cd /etc/nginx
    ls
    
    • 端口暴露概念图

    在这里插入图片描述

    思考问题:如果每次改动 nginx 配置文件,都需要进入容器内部改动吗?非常麻烦,如果能在容器外部提供一个映射路径,让我做到在容器外部修改文件,容器内部就能够自动修改,这样就非常方便了。这就是之后要学的 -v数据卷 技术。

    作业2、使用 docker 安装 tomcat (学习官方测试和进入容器查看内容)

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    # 官方的使用
    # 我们之前的启动都是后台,停止了容器之后,容器还是可以查到
    #  --rm 的意思是 用完即删 停止之后就将容器删除 一般用来测试
    docker run -it --rm tomcat:9.0
    
    
    # 我们要使用的还是要按照正常流程来使用
    # 1、拉取 下载tomcat9。如不指定版本 默认是装新的版本
    docker pull tomcat:9.0
    # 2、查看镜像
    docker images
    # 3、创建容器运行镜像 -d 后台运行 -p 指定端口 主机的3355映射到容器的8080端口 -name为自定义的名 
    docker run -d -p 3355:8080 --name tomcat01 tomcat:9.0
    docker run -it -p 8080:8080 tomcat   #简化创建tomcat容器的命令
    # 4、查看
    docker ps
    # 5、测试访问 http://39.106.230.179:3355/ 但是发现是404页面找不到
    # 6、根据名称进入相关tomcat容器内
    docker exec -it tomcat01 /bin/bash
    ls -al
    # 7、查看webapps文件夹
    cd webapps
    ls   /   ls -al
    # 8、发现目录是空的
    # 9、原来这个官方镜像是阉割版的,很多的文件都是没有配置的
    #    阿里云镜像的原因,默认是最小的镜像,所有不必要的都剔除了,保证做小可运行的环境
    #      a. 少了一些Linux命令,例如 ll 命令
    #      b. webapps 目录为空
    #    解决办法: 容器内的根目录里面有一个 webapps.dist 文件夹,里面就包含了默认的例子
    #              这样可以将文件夹里面的内容拷贝到webapps下 cp -r webapps.dist/* webapps
    

    思考问题又来了:如果每次部署项目都要进入容器,就会非常的麻烦,那这个答案就很显而易见了,我们可以利用卷技术与外部自动同步,就不用每次都进入了。

    作业3、部署 ES + kibana (学习查看容器状态和修改)

    注意:安装ES特别占用内存,1.2G,提前关闭不用的服务

    难点:
     1、es 需要暴露的端口非常多
     2、es 十分耗内存
     3、es 的数据一般需要放置到安全目录 ==> 可用挂在解决
    
    # 1、老规矩搜索安装启动
    #    --net somenetwork ? 网络配置 先去掉
    docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:7.7.1
    
    # 启动之后 linux会非常卡 可以使用 docker stats 查看cpu状态
    CONTAINER ID        NAME                CPU %               MEM USAGE / LIMIT   MEM %               NET I/O             BLOCK I/O           PIDS
    7d399bee6df4        elasticsearch       0.45%               1.229GiB / 3.7GiB   33.20%              0B / 0B             0B / 0B             50
    c92ee0f0ac1c        tomcat01            0.15%               76.88MiB / 3.7GiB   2.03%               0B / 0B             0B / 0B             36
    # 可以看到占用内存非常大
    # 2、测试一下是否启动成功了
    [root@admin ~]# curl localhost:9200
    {
      "name" : "7d399bee6df4",
      "cluster_name" : "docker-cluster",
      "cluster_uuid" : "BRfKhOPTS52FScc55t3vew",
      "version" : {
        "number" : "7.7.1",
        "build_flavor" : "default",
        "build_type" : "docker",
        "build_hash" : "ad56dce891c901a492bb1ee393f12dfff473a423",
        "build_date" : "2020-05-28T16:30:01.040088Z",
        "build_snapshot" : false,
        "lucene_version" : "8.5.1",
        "minimum_wire_compatibility_version" : "6.8.0",
        "minimum_index_compatibility_version" : "6.0.0-beta1"
      },
      "tagline" : "You Know, for Search"
    }
    
    # 3、赶紧关闭,增加内存使用的限制  修改配置文件 -e 环境配置修改
    #    就是再启动命令上增加参数,限制内存的使用
    #    -e ES_JAVA_OPTS="-Xms64m Xmx512m"
    docker run -d --name elasticsearch02 -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms64m -Xmx512m" elasticsearch:7.7.1
    
    • 那么问题如期而至,该怎么使用kibana连接es呢?网络如何才能连接过去呢?首先要了解一个基本的模型,其次还要学习一些网络上面的知识。先为后面的内容埋下伏笔。【可以在 Docker 网络 那个章节找到答案】
      在这里插入图片描述

    Docker 可视化

    有两种工具:

    • portainer(先用着,不是最佳选择)
    • Rancher(CI/CD再用)

    什么是 portainer ?

    • Docker 图形化界面管理工具,提供一个后台面板供我们操作
    • 安装:
    #简化版命令 此处不使用
    docker run -d -p 8088:9000
    
    # --restart=always 启动方式
    # -v /var/run/docker.sock:/var/run/docker.sock 挂载
    # --privileged=true 权限
    docker run -d -p 8088:9000 --restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer
    
    • 访问测试:公网ip地址:8088 或者本地测试 curl localhost:8088

    进入后设置访问的用户名 密码。创建用户
    在这里插入图片描述

    进入之后首先会让你创建用户,然后选择Local,就能进入一个控制面板

    在这里插入图片描述

    在这里插入图片描述

    可视化面板完成


    Docker 镜像讲解

    什么是镜像?

    镜像是一种【轻量级、可执行的独立软件包】,用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需的【所有内容】,包括【代码、运行时、库、环境变量和配置文件】

    所有的应用,直接打包docker镜像,就可以直接跑起来!

    那么如何得到镜像呢?

    • 从远程仓库下载
    • 朋友拷贝
    • 自己制作一个镜像 Dockerfile

    Docker 镜像加载原理

    UnionFS(联合文件系统)

    我们下载的时候看到的一层层的就是这个!

    UnionFS(联合文件系统):是一种【分层、轻量级并且高性能】的文件系统,它支持对文件系统的修改,作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite directories into a single virtual filesystem)。UnionFS是Docker镜像的基础,镜像可以通过分层来继承,基于基础镜像(没有父镜像的镜像),可以制作各种具体的应用镜像

    【特性】一次同时加载多个文件系统,但从外面看起来只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录

    【例子】:比方说 mysql 和 tomcat 都需要 centos 环境,那我先安装了 mysql ,就有了 centos 的环境,那我要再安装 tomcat ,就可以共用这一层 centos ,不需要再下载 centos 。

    Docker 镜像加载原理

    Docker的镜像实际上由一层一层的文件系统组成,这种层级的文件系统UnionFS。

    BootFS(Boot file system)主要包含 bootloader 和 kernel,bootloader 主要是引导加载 kernel,Linux 刚启动时会加载 BootFS文件系统,在 Docker 镜像的最底层是 BootFS。这一层与我们典型的 Linux/Unix 系统是一样的,包含 boot 加载器 和 内核。当 boot 加载完成之后整个内核就都在内存中了,此时内存的使用权已由 BootFS 转交给内核,此时系统也会卸载 BootFS。

    RootFS(Root File System),在 BootFS 之上,包含的就是典型 Linux 系统中的 /dev,/proc,/bin,/etc 等标准目录和文件。RootFS就是各种不同的操作系统发行版,比如 Ubuntu CentOS 等等。

    在这里插入图片描述

    问题来了,平时我们安装进虚拟机的 CentOS 都是好几个G,为什么Docker这里才200M?

    那是因为对于一个精简的OS,RootFS可以很小,只需要包含最基本的命令,工具和程序库就可以了,因为底层直接用 Host 的 kernel,自己只需要提供 RootFS 就可以了,由此可见对于不同的 Linux 发行版, BootFS 基本是一致的,RootFS 会有差别,因此不同的发行版可以公用 BootFS。

    虚拟机是分钟级别,容器是秒级

    分层理解

    分层的镜像

    可以观察一下下载一个镜像的时候的日志输出,会发现是一层一层的在下载的
    在这里插入图片描述

    【问】为什么Docker镜像要采用这种分层的结构呢?

    【答】最大的好处莫过于是资源共享了。比方说有多个镜像都从相同的 base 镜像构建而来,那么宿主机只需要在磁盘上保留一份 base 镜像,同时内存中也只需要加载一份 base 镜像,这样就可以为所有的容器服务了,而且镜像的每一层都可以被共享。

    我们可以通过 docker inspect 命令从 查看镜像分层

    在这里插入图片描述

    【加深理解】
    所有的 Docker 镜像都起始于一个基础镜像层,当进行修改或增加新的内容时,就会在当前镜像层之上创建新的镜像层。

    【例子】第一层镜像:基于 Ubuntu Linux 16.04 创建一个新的镜像;如果在这个镜像中添加 Python 包,就会在基础镜像层上创建第二个镜像层;如果继续添加一个安全补丁,就会创建第三个镜像层,如下图。

    在这里插入图片描述

    在添加额外的镜像层的同时,镜像始终保持时当前所有镜像的组合,理解这一点非常重要,下图中举了一个简单的例子,每个镜像层包含3个文件,而镜像包含了来自两个镜像层的6个文件
    在这里插入图片描述

    上图中的镜像层跟之前图中的略有区别,主要目的是便于展示文件。

    下图中展示了一个稍微复杂的三层镜像,在外部看来整个镜像只有六个文件,这是因为最上层中的文件 7 是 文件 5 的一个更新版本
    在这里插入图片描述

    这种情况下,上层镜像层中的文件覆盖了底层镜像层中的文件。这样就使得文件的更新版本作为一个新镜像层添加到镜像当中。

    Docker 通过存储引擎(新版本采用快照机制)的方式来实现镜像层堆栈,并保证多镜像层对外展示为统一的文件系统。

    Linux 上可用的存储引擎有 AUFS、OverLay2、Device Mapper、Btrfs、以及 ZFS。顾名思义,每种存储引擎都基于Linux中对应的文件系统或者块设备技术,并且每种存储引擎都有其独有的性能特点。

    Docker 在 Windows 上仅支持 windows filter 一种存储引擎,该引擎基于 NTFS 文件系统之上实现了分层和 CoW

    下图展示了与系统显示相同的三层镜像。所有镜像层堆叠并合并,对外提供统一的视图。
    在这里插入图片描述

    特点

    Docker 镜像都是【只读】的,当容器启动时,一个新的可写层被加载到镜像的顶部!

    这一层就是我们通常说的【容器层】,容器之下的都叫【镜像层】
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DReKxq75-1593050117124)(D:/typora/Typora/img/Docker 2020最新版 超详细/1592732066425.png)]

    commit 镜像

    docker commit    提交容器成为一个新的副本
    
    docker commit -a="作者" -m="提交的描述信息" 容器id 目标镜像名[tag]
    
    测试:
    docker run -it -p 8080:8080 tomcat  启动tomcat容器
    docker exec -it 容器id /bin/bash  进入到tomcat的控制台
    
    前面说到 tomcat 容器的 webapps 下是没有文件的
    那每次启动的时候都要将 webapps.dist 目录下的内容拷贝到 webapps 目录下
    我现在自己拷贝进去了一些基本的应用   => cp -r webapps.dist/* webapps/
    
    #自己打包一个镜像,方便日后使用
    docker commit -a="tizi" -m="add webs app" bc7 tomcat_new:diy
    #查看镜像
    docker images
    REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
    tomcat_new          diy                 9d7965108263        3 seconds ago       652MB
    centos             latest              831691599b88         4 days ago          215MB
    tomcat              9.0                 2eb5a120304e        11 days ago         647MB
    tomcat             latest              2eb5a120304e        11 days ago          647MB
    nginx              latest              2622e6cca7eb        11 days ago          132MB
    portainer/portainer   latest           cd645f5a4769        2 weeks ago         79.1MB
    elasticsearch       7.7.1              830a894845e3        3 weeks ago          804MB
    
    可以看到我们自己生成的存储要大一些
    

    要先理解概念,即使模棱两可,然后一定要去实践,最后实践和理论相结合,总结搞定这个知识点

    • 如果想要保存当前容器的状态,就可以通过 commit 来提交,获得一个镜像,下次直接使用这个镜像启动容器即可,就好比使用虚拟机时候的快照

    容器数据卷

    什么是容器数据卷?

    【需求】

    • 很多时候我们的应用会有很多数据,如果数据放在容器里面,只要容器删除了,数据就会丢失,这个就很容易让人删库跑路了,所以我们希望【数据可以持久化】,也就是【数据存储在本地而不是容器
    • 这样就催生出容器之间的数据共享的技术,Docker 容器中产生的数据可以同步到本地!
    • 这就是卷技术,也就是数据的挂载,将容器内的目录,挂载到主机上

    使用卷技术就是为了容器的持久化和同步操作!容器间的数据也可以共享!

    使用数据卷

    方式一:直接使用命令来挂载数据 (方式二在 《初始 DockerFile》)

    docker run -it -v 主机目录:容器内目录
    
    测试:将容器的home目录挂载到主机的home目录下的ceshi目录
    docker run -it -v /home/ceshi:/home centos /bin/bash
    
    进入容器后,进入 home 目录,新建一个文件
    touch hello.txt
    ls 查看目录下的内容,能看到这个文件
    这个时候切换到主机,或者再开一个终端查看主机的 home 目录下的 ceshi 目录
    cd /home/ceshi
    ls 查看目录下的内容,发现 hello.txt 文件已经同步过来了
    
    那我们再来测试,当我们关掉容器之后数据还能同步吗?
    docker exec -it 容器id /bin/bash
    1、先 exit 退出容器
    2、docker ps 查看容器是否真的停止了
    3、主机上 vim /home/ceshi/hello.txt 修改文件
    4、docker start 启动容器
    5、容器内 cat /home/hello.txt 查看文件内容
    能够发现文件内容跟之前修改的是一样的,表示文件已经同步过来了,当删除或创建添加文件都同步
    
    docker inspect 容器id #查看挂载信息 
    

    在这里插入图片描述

    • 这个的好处就是以后修改只需要在本地修改即可,容器内会【自动同步】

    MySQL 同步数据

    1、先获取 mysql 镜像 这里使用 5.7 版本
    docker pull mysql:5.7
    2、运行容器 同时挂载数据和配置文件 【注意】mysql启动需要配置密码
    docker run -d -p 3306:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql mysql:5.7
    3、启动成功之后,可以使用navicat来连接一下mysql 或者 docker exec -it 进入容器 mysql -p 进入 mysql 控制台
    4、创建一个数据库,再查看主机上映射的路径,就能查看到刚刚新创建的数据库文件
    5、来波刺激的,删除调这个容器 docker rm -f mysql01
    6、再去查看刚刚的路径 cd /home/mysql/data 然后 ls 查看文件
    7、能发现文件依然存在,没有丢失,这就实现了【容器数据持久化】的功能
    
    

    通过以上设定的端口可连接到mysql数据库
    在这里插入图片描述

    在数据库中创建数据库,在linux home的data目录下,可看到会多出新建的数据库。

    当删除mysql容器后,再次运行 同样的创建mysql容器命令,数据还在

    具名和匿名挂载

    • 匿名挂载
    -v 容器内路径   【不去写主机上的路径,会自动创建一个路径】
    -P  【大写的P,随机指定端口】
    docker run -d -P --name nginx01 -v /etc/nginx nginx
    安装之后可以通过 docker volume 查看卷
    可以通过 docker volume --help 查看可选项
    docker volume ls 显示卷列表
    能够发现卷的名称是一串字符,这种就是匿名挂载
    我们在 -v 的时候只写了容器内的路径,没有写容器外的路径
    

    在这里插入图片描述

    • 具名挂载
    如果路径前面有 / 则代表是绝对路径,如果没有,就代表只是一个名字,而不是一个目录
    docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx nginx
    
    再查看卷列表 docker volume ls
    就能看到我们命名为 juming-nginx 的卷
    
    通过 -v 卷名:容器内路径 来为卷命名
    
    那我们也可以通过这个卷名来查看路径
    docker volume inspect juming-nginx
    

    在这里插入图片描述

    • 所有的 docker 容器内的卷,没有指定目录的情况下都是在:【/var/lib/docker/volumes/xxxx/_data
    • 我们通过具名挂载可以方便的找到我们的一个卷,大多数情况也是在使用【具名挂载】

    那么问题来了,我们该如何确定是具名挂载还是匿名挂载,亦或是指定路径挂载呢?

    -v 容器内路径     =>  匿名挂载
    -v 卷名:容器内路径     =>  具名挂载
    -v /宿主机路径:容器内路径     =>  指定路径挂载 会有一个 / 表示绝对路径
    

    【拓展】:

    • 有时候我们会遇到这样一些命令,路径后面跟着一个 ro 或 rw
      docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx:ro nginx
      docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx:rw nginx
    • 这个可以用来改变读写权限 【read-only】 和 【read-write】,一旦设置了容器的权限,容器对我们挂载出来的内容就有限定了
    • ro 只要看到 ro 就说明这个路径只能通过宿主机来操作,容器内部是无法操作的,默认为 rw

    初识 DockerFile

    Docker File 就是用来【构建 docker 镜像】的构建文件。是一段【命令脚本】,可以通过这个脚本生成镜像。

    镜像是一层一层的,那么对应的,这个脚本就是一个个的命令,每个命令就是镜像的一层。

    方式二:在自己搭建的镜像中设置 启动镜像的时候就自动挂载

    我们先来做个小测试:
    在这里插入图片描述

    在这里插入图片描述

    • 那我们来启动一下这个镜像,查看一下内容

    在这里插入图片描述

    • 既然是数据卷,那么在外部就一定有一个同步的目录,另外,因为我们【只写了容器内的目录,所以这是个匿名挂载】,那我们找的话,卷名应该是一个不规则的字符串。
    • 还记得我们前面的 inspect 命令吗,它能查看镜像的详细信息,其中有一个 Mounts 节点,保存了挂载点的信息,我们就可以在这里去查看挂载点的信息【先docker ps查看镜像ID,再docker inspect 镜像ID查看】
      在这里插入图片描述
    • 我们再创建一个文件试试
      在这里插入图片描述
    • 这种方式以后使用会十分多,因为我们通常会构建自己的镜像,加入构建镜像的时候没有挂在卷,要手动挂载【-v 卷名:容器内路径】
    # 1.创建脚本文件
    /home/ mkdir docker-test-volume
    
    cd mkdir docker-test-volume/vim dockerfile1 
    
    # 输入以下内容
    FORM centos
    
    VOLUME ["volume01","volume02"]
    
    CMD echo "---end---"
    CMD /bin/bash
    # 2.启动自定义脚本 注意.
    docker build -f /home/docker-test-volume/dockerfile1 -t tizi/centos:1.0 .
    
    #成功后 docker images 下 可查看到根据脚本生出的镜像
    
    #启动自己写的镜像容器
    docker run -it 容器id /bin/bash
    
    #进入到容器
    docker exec -it 容器id /bin/bash
    docker attach 容器id
    #写入一个文件
    cd volume01
    touch a.java
    
    #查看挂载信息
    docker inspect 容器id
    

    数据卷容器

    • 【使用场景】:多个mysql 同步数据
      在这里插入图片描述

    【上手操作】

    #通过我们刚才生成的镜像来启动两个容器 docker01 和 docker02
    #通过自己定义的centos指定版本来创建容器1
    docker run -it --name docker01 tizi/centos:1.0
    #通过自己定义的centos指定版本来创建容器2 --volumes-from docker01 类似于02继承01,同步数据
    docker run -it --name docker02 --volumes-from docker01 tizi/centos:1.0
    然后进入 docker01 中,进入 volume01 目录下,新建一个 docker01 文件
    再进入 docker02 中,进入 volume01 目录下,查看目录内容
    能发现两个容器之间的数据已经同步了
    

    在这里插入图片描述

    在这里插入图片描述

    也许有人要问了:能不能再来个 docker03 再去挂载 docker01 呢?那就来尝试一下!

    docker run -it --name docker03 --volumes-from docker02 tizi/centos:1.0
    
    在volume01创建文件 可发现1和2容器 都会获得到,数据共享了。
    当删除3时,其他容器数据仍在,包含3的内容。
    和拷贝 备份的原理相同
    

    在这里插入图片描述

    • 所以我们只要通过 --volumes-from 创建容器,就能实现容器之间的数据共享。【注意】这个数据共享是即使创建这个文件的容器被删了,文件依旧存在。
    • 更像是一种引用,数据卷容器挂载到宿主机的目录中,然后其他的容器挂载到数据卷容器时,使用的是对该文件的引用(数据地址的拷贝),如果是将文件进行拷贝,不仅效率低,而且浪费空间。:

    例:多个MySQL实现数据共享

    docker run -d -p 3310:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7
    
    docker run -d -p 3310:3306 -e MYSQL_ROOT_PASSWORD=123456 --name mysql02 --volumes-from mysql01 mysql:5.7
    

    小结

    • 容器之间配置信息的传递可以通过数据卷进行集中管理,或者实现复用
    • 数据卷容器的生命周期会一直持续到没有容器使用位置,但是一旦你持久化到了本地,这个时候,本地的数据是不会删除的
    • 本章主要讲解了两种挂载方式,一个是通过 -v 命令来挂载,另一个就是我们再构建 DockerFile 的时候将挂载目录写入镜像中。
    • 其中,挂载有两种方式:具名挂载和匿名挂载
    • 然后,还介绍了容器之间进行数据共享的方式【 --volume-from 挂载到数据卷容器】

    Docker File

    DockerFile 介绍

    DockerFile 的核心是用来构建 docker 镜像的文件,是一个命令参数脚本

    构建步骤:
    1、编写一个 dockerfile 文件
    2、docker build 构建成为一个镜像
    3、docker run 运行镜像
    4、docker push 发布镜像(DockerHub、阿里云镜像仓库)

    • 我们可以查看官方是怎么做的:
      在这里插入图片描述


    在这里插入图片描述

    • 很多官方镜像都是基础包,很多功能是没有的,通常我们都会自己搭建一个镜像!

    DockerFile 构建过程

    基础知识

    • 每个保留关键字(指令)必须是大写字母

    • 指令是从上到下 顺序执行

    • #号表示注释

    • 每一个指令都会创建提交一个新的镜像层
      在这里插入图片描述

    • dockerfile 是面向开发的,我们以后发布项目,做镜像,提交文件。就需要编写 dockerfile 文件,这个文件十分简单

    相关名词解释

    Dockerfile:构建文件,定义了一切的步骤,相当于源代码
    DockerImages:通过 Dockerfile 构建生成的镜像,最终发布和运行的产品,相当于原来的 war包、jar包
    Docker容器:容器就是镜像运行起来提供服务的

    DockerFile 指令

    FROM          #基础镜像 例如 centos/ubuntu  一切从这里开始构建
    MAINTAINER    #镜像是谁写的,一般是姓名+邮箱
    RUN           #镜像构建的时候需要运行的命令
    ADD           #步骤 比如说要添加tomcat,就需要一个tomcat的压缩包,这个压缩包就是要添加的内容
    WORKDIR       #镜像的工作目录
    VOLUME        #挂载的目录
    EXPOSE        #指定暴露端口配置
    CMD           #指定这个容器启动的时候要运行的命令,只有最后一个会生效,会被替代
    ENTRYPOINT    #指定这个容器启动的时候要运行的命令,可以追加命令
    ONBUILD       #当构建一个被继承的 DockerFile 这个时候就会运行 ONBUILD 指令
    COPY          #类似 ADD 命令,将文件拷贝到镜像中
    ENV           #构建的时候设置环境变量
    

    在这里插入图片描述

    • 接下来我们就可以写一个自己的镜像啦!

    实战:构建一个自己的CentOS

    • 我们先看一下官方的 CentOS 的 DockerFile
      在这里插入图片描述

    • DockerHub 中绝大部分的镜像都是从这个基础镜像过来的 FROM scratch ,然后配置需要的软件和配置来进行构建

    • 那我们就基于官方的这个镜像,再加一些我们需要的环境

    构建前先启动官方提供的centos,会发现功能少
    docker run -it centos
    pwd    #会在根目录
    vim	   #无内容
    ifconfig
    根据以上的情况我们自己构建一个升级版的centos
    
    1、先进入一个目录,创建一个 dockerfile 目录迎来存放一些文件
       cd /home
       mkdir dockerfile
    2、创建一个dockerfile文件,命名就随便,这里命名为 mydockerfile
       vim mydockerfile
    3、开始写指令(复制时去掉标注的说明)
       FROM centos      # 基础镜像
       MAINTAINER tizi<  <xxxxxxx@qq.com>    # 作者信息
    
       ENV MYPATH /usr/local    # 创建一个变量 存放一个值
       WORKDIR $MYPATH    # 启动后的工作目录,就是进入容器后的默认目录
    
       RUN yum -y install vim    # 执行指令安装 vim
       RUN yum -y install net-tools    # 执行指令安装 net-tools
    
       EXPOSE 80    # 暴露端口
    
       CMD echo $MYPATH    # 输出 MYPATH 变量
       CMD echo "------end---------"    # 输出信息
       CMD /bin/bash    # 启动后用bash命令行
    4、构建镜像
       docker build -f mydockerfile -t mycentos:0.1 .
    5、构建成功 末尾输出的内容
       Successfully built fa1d3cda51dc
       Successfully tagged mycentos:0.1
    6、测试运行
       docker images #查看自己构建的centos
       docker run -it mycentos:0.1 #运行自己构建的centos
    7、我们可以通过 history 命令查看一下运行过的指令
       docker history 镜像ID
    

    CMD 和 ENTRYPOINT 的区别

    • 【CMD】指定这个容器启动的时候要运行的命令,只有最后一个会生效,会被替代
    • 【ENTRYPOINT】指定这个容器启动的时候要运行的命令,可以追加命令

    以下步骤建议上手操作一下

    1、创建一个 dockerfile ,写入
       FROM centos
       CMD ["ls","-a"]
    2、构建镜像
       docker build -f dockercmd -t cmdtest .
    3、直接运行镜像
       docker run 镜像id
    4、能发现 ls -a 命令生效了
    5、我们现在想追加一个 -l 命令,就是执行 ls -al 命令
       根据之前的内容,我们可以在 docker run 命令后面加上 -l 命令作为参数
       即 docker run a9d76c1b34d2 -l
       但是当我们确认执行过后,却发现报错了
       docker: Error response from daemon: OCI runtime create failed: container_linux.go:349: 
       starting container process caused "exec: \"-l\": executable file not found in $PATH": unknown.
       ERRO[0000] error waiting for container: context canceled 
       为什么呢?因为 CMD 的情况下,-l 替换了 CMD ["ls","-a"] 命令,但是 -l 又不是命令,所以就报错了。
       那我们可以直接加上完整的命令进行追加【docker run a9d76c1b34d2 ls -al】这样就能执行成功了,不过非常麻烦
    6、引入 ENTRYPOINT 进行操作,重新创建一个 dockerfile
       FROM centos
       ENTRYPOINT ["ls","-a"]
    7、重新构建运行
       docker build -f dockerentrypoint -t entrypointtest .
       docker run 7855e875f6e1
       截至到这一步为止,结果都跟使用CMD没有什么差别
    8、docker run 命令后追加 -l
       docker run 7855e875f6e1 -l
       会发现结果不仅没报错,而且还跟执行 ls -al 一样,这样就能看出这两个命令之间的差距
       表示这里 -l 命令是直接拼接在 ENTRYPOINT 命令的后面的
    

    Dockerfile 中很多命令都是十分相似的,我们需要了解他们的区别,最好的学习方法就是对比学习然后测试效果。

    实战:制作一个 Tomcat 镜像

    此方式生成的镜像有问题,tomcat的webapp目录没有文件,curl localhost:9090或浏览器运行会报错

    具体别的方式完成可参考 https://blog.csdn.net/weixin_43397326/article/details/83306562

    或者搜索别的内容参考

    1. 准备镜像文件:tomcat 安装包、jdk 安装包(tar包)
    2. 在Linux根目录创建resource,在resource下创建docker_tomcat_jdk文件,在此目录下创建readme.txt(可不建) 。vim dockerfile。根据自己创建
    3. 编写 dockerfile 文件,官方命名【Dockerfile】,build 会自动寻找这个文件,就不需要 -f 指定了
    注意 复制时去掉注释。写完后要在docker_tomcat_jdk文件下运行。不然需要指定文件 加上 -f
    运行命令:docker build -t 自定义名 .
    如在其他文件下运行 参考命令(容易报错,不推荐):
    docker build -f resource/docker_tomcat_jdk/dockerfile -t diytomcat .
    
    FROM centos	# 基本系统的镜像,在此基础上构建
    MAINTAINER xiangt>iti@66666@qq.com	# 作者信息
    
    COPY readme.txt /resource/dockerfile/readme.txt	 # 复制readme到容器内部的这个路径
    
    ADD jdk-8u161.tar.gz /usr/local/	 # ADD 命令会自动解压 将tar包解压到指定的路径,通过linux安装也是会自动放入到 usr/local中
    ADD apache-tomcat-9.0.36.tar.gz /usr/local
    
    RUN yum -y install vim	# 安装一些基本命令
    
    ENV MYPATH /usr/local	# 设置默认的工作目录
    WORKDIR $MYPATH
    
    ENV JAVA_HOME /usr/local/jdk1.8.0_161	# java 环境变量的配置
    ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
    ENV CATALINA-HOME /usr/local/apache-tomcat-9.0.36	# tomcat 环境变量
    ENV CATALINA-BASH /usr/local/apache-tomcat-9.0.36	
    ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin
    
    EXPOSE 8080  # 暴露 tomcat 端口为8080
    # 启动 tomcat 可以通过 && 拼接一些参数  tail -F 显示文件新追加的内容
    CMD /usr/local/apache-tomcat-9.0.36/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.36/bin/catalina.out
    
    1. 构建镜像【docker build -t diytomcat .】文件命名为Dockerfile后可以不用 -f 指定文件,能自动匹配
    2. 构建完后就运行,会和-v指定目录挂载数据【docker run -d -p 9090:8080 --name zdyTomcat -v /resource/tomcatdiy_juan:/usr/local/apache-tomcat-9.0.36/webapps diytomcat
    3. 访问测试:进入容器内查看目录【docker exec -it 容器id /bin/bash】【ls -l
    4. 发布项目,因为我们将 webapps 目录挂载在宿主机的一个目录,所以可以直接在本地编写项目
    5. 访问 tomcat 服务器内的应用,测试查看是否成功

    发布自己的镜像到 DockerHub

    地址:https://hub.docker.com/

    1. 要先注册一个账号
    2. 确定这个账号可以登录
    3. 在我们的服务器上提交自己的镜像
    1、先在命令行上登录 输入命令后会让你输入密码,出现 Login Succeeded 表示登录成功
       docker login -u dockerhub的用户名
    2、提交镜像 docker push 不带版本号就是提交最新版 latest 
       这里就要求我们在构建镜像的时候就带上账号名,以防混乱
       docker push 用户名/mycentos
       如果没带上 tag,报错加上即可。默认是 latest,推荐加上tag
       重新打 tag 的命令:  docker tag 用户名/mycentos 用户名/mycentos:1.0
    

    发布到阿里云镜像仓库上

    1. 登录阿里云

    2. 搜索找到 容器镜像服务
      在这里插入图片描述

    3. 创建命名空间,为了隔离防止镜像冲突
      在这里插入图片描述

    4. 创建镜像仓库:填写信息,选择【本地仓库】
      在这里插入图片描述

    5. 浏览一下这个仓库信息【点击蓝色的仓库名】
      在这里插入图片描述

    6. 跟着操作指南来操作,提交镜像,【参考官方文档即可】

    7. sudo docker login --username=ti66666@vip.qq.com registry.cn-beijing.aliyuncs.com。登上阿里云仓库

    8. docker push mysql:5.7

    小结

    • 一个流程图能很好的梳理这一章的知识点
      在这里插入图片描述

    Docker 网络

    理解【Docker0】

    • Docker 网络的核心就是 【Docker0】

    • 我们可以用 ip addr 查看一下宿主机的 ip 信息
      在这里插入图片描述

    • 【问题】 docker 是如何处理容器网络访问的?

    • 比如说现在有两个容器(A 容器和B 容器),那么现在 A 容器的 Tomcat 里面的应用要访问 B 容器的 MySql,这里是怎么进行连接的呢?是用上面三个地址的哪一个地址进行访问的呢?

    • 前面我们配置 ES 的时候也提出过这样的问题,怎么样让 kibana 连接上 ES 呢?

    1、我们先运行一个 tomcat 镜像,再查看一下网卡
       docker run -d -P --name tomcat01 tomcat
       docker exec -it tomcat01 ip addr
       我们能发现容器启动的时候会得到一个 eth0@if81 这样的标识,这是 docker 分配的
       ----- 运行结果 -----
       1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
           link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
           inet 127.0.0.1/8 scope host lo
              valid_lft forever preferred_lft forever
       80: eth0@if81: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
           link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
           inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
              valid_lft forever preferred_lft forever
       -------------------
    2、我们来试一试能不能 ping 容器内部
       ping 172.17.0.2
      发现能够 ping
    • 【分析】

      • 我们看回前面的 docker0 的地址,发现是 172.17.0.1 ,能发现这个跟我们平时路由器的地址 192.168.0.1 很像
      • 当我们用手机连上这个路由器的 wifi 的时候,分配的 ip 地址就是 192.168.0.3 之类的,这两个 ip 在一个网段内,就能互相 ping 通
      • 同样的道理,我们测试的容器的 ip 地址是 172.17.0.2 ,这个跟 172.17.0.1 是同一个网段的,那肯定能 ping 通了
      • 每当我们启动一个 docker 容器,docker 就会给容器分配一个 ip ,我们只要安装了 docker,就会有一个网卡 docker0
      • 这个网卡使用的是桥接模式,使用的技术是 veth-pair 技术
    • 当我们创建完容器之后再使用 ip addr 查看网卡
      在这里插入图片描述

    • 有没有发现出什么!!??

    • 我们创建完容器之后查看到的网卡中有一个是【80: eth0@if81】,刚好就和上图的网卡是相反的

    • 那我们再启动一个 tomcat 容器呢?
      在这里插入图片描述

    • 发现又多了一对网卡,注意,是【一对】!这种一对一对出现的网卡就是因为使用了 veth-pair 技术

    • veth-pair 就是一对的虚拟设备接口,他们都是成对出现的,一端连着协议,一端彼此相连

    • 正因为有这个特性,通常用这个技术来充当桥梁,连接各种虚拟网络设备

    • 例如 OpenStack Docker容器之间的连接 ovs的连接 都是使用了 veth-pair 技术

    • 我们来试试在 tomcat01 ping tomcat02
      在这里插入图片描述

    • 所以容器和容器之间是可以 ping 通的!
      在这里插入图片描述

    • 当我们在 2 去 ping 3 的时候,或先通过 veth-pair技术 从 261 转发到 262 上,1 再通过保存的端口注册信息,再从 264 发到 263 ,这样就完成了一次数据通信,而不是直接从 2 发送到 3 上面,这就是桥接的概念。

    • 这里有两种机制,一个类似路由转发,直接转发到特定的端口上面;一个是广播,散发出去,查看那个端口接收处理了。

    • 如果学过《计算机网络》的会比较好理解,不懂的话建议自己去找一些资料看一下。

    • 所有容器在不指定网络的情况下,都是 docker0 路由的,docker 会给我们的容器分配一个默认的可用 ip,可以看下不指定ip启动tomcat,docker ps一下,有一个docker0随机生成的的端口

    • 可以使用 -net 指定网络

    小结

    • Docker 使用的是 Linux 的桥接,宿主机中是一个 Docker 容器的网桥【docker0】
    • Docker 中的所有的网络接口都是虚拟的,而且虚拟的转发效率高!
    • 只要容器删除了,对应的一对网桥就没了
      在这里插入图片描述

    容器互联 --link 命令

    思考一个场景,我们编写了一个微服务,需要通过一个URL连接数据库,那每次启动容器,就会重新分配 IP,IP就会变动,URL地址也就会失效了。

    • 在学习 springcloud 的时候,学过 feign ,feign 调用是通过服务名来调用的,就是后面的 IP 不管怎么变,我都能通过固定的服务名来调用
    • 那么类似的,如果我们能够通过【容器名】来 ping 通,就能做到即使 IP 改变了,我依然能够连接上去
    • 这样我们也就能实现【高可用】了
    1、我们先来尝试一下能不能通过容器名 ping[root@admin ~]# docker exec -it tomcat02 ping tomcat01
    ping: tomcat01: Name or service not known
    发现不能 ping 通
    
    2、新创建一个 tomcat03 容器 使用 --link 
    [root@admin ~]# docker run -d -P --name tomcat03 --link tomcat02 tomcat
    d6f626ab5aa0f56f48e56ae2c2603444d19c2c96e7e56a5fa15bcbbf692d0869
    
    3、在 tomcat03 使用容器名 ping tomcat02 
    [root@admin ~]# docker exec -it tomcat03 ping tomcat02
    PING tomcat02 (172.17.0.3) 56(84) bytes of data.
    64 bytes from tomcat02 (172.17.0.3): icmp_seq=1 ttl=64 time=0.121 ms
    64 bytes from tomcat02 (172.17.0.3): icmp_seq=2 ttl=64 time=0.078 ms
    发现 ping 通了!!!
    
    4、但是,当我们在 tomcat02 使用容器名 ping tomcat03 时,结果却不如我们所愿
    [root@admin ~]# docker exec -it tomcat02 ping tomcat03
    ping: tomcat03: Name or service not known
    结果却 ping 不通了
    
    • 这是因为在 tomcat02 中没有配置,我们在 tomcat03 中配置了 --link ,但是在 02 中却没有配置

    【探究】

    • 我们来查看一下 docker 的网络的元数据信息
    1、查看 docker 网络列表
       docker network ls
    NETWORK ID          NAME                DRIVER              SCOPE
    7bc4edf2a0e8        bridge              bridge              local
    de44533d6de3        host                host                local
    32983fccf962        none                null                local
    
    2、我们查看一下第一个
       docker network inspect 7bc4edf2a0e8
    

    在这里插入图片描述

    • 继续往下翻,看看后面还有什么

    在这里插入图片描述

    • 这里我们能看到三个容器的网络信息

    • 接下来我们查看一下我们刚刚创建的 tomcat03 容器的配置信息,其中在 HostConfig 里面有一个 Links
      在这里插入图片描述

    • 根据 DNS解析 的流程,当我们访问一个域名/地址,会首先去查看 host 文件,那我们也能查看一下 tomcat03 的 host 文件
      在这里插入图片描述

    • 这就代表着我们只要请求 tomcat02,就会直接转发到 172.17.0.3,所以就可以 ping 通

    • --link 就是我们在 host 配置中增加了 tomcat02 的映射

    • 当 IP 变了,就表示容器重启了,那么--link重新链接,配置文件也就自动改了

    • 我们可以再看一下 tomcat02 没有配置的容器的 host 文件和镜像元数据中的连接配置信息
      在这里插入图片描述
      在这里插入图片描述

    • 可以发现,tomcat02 里面就没有这些配置

    • 其实这个的本质就是 host 映射,这种方式太笨了,【不建议使用】,我们需要更高级的

    • 我们需要的是【自定义网络】,不适用【docker0】,docker0 是官方的网桥,是局限的

    • 比方说 docker0 【不支持容器名连接访问】

    • 所以进阶的操作是使用【自定义网络】

    自定义网络

    查看所有的 docker 网络

    在这里插入图片描述

    • 网络模式

      • bridge :桥接模式【 docker上搭桥(默认)】
      • host:主机模式【和宿主机共享网络】
      • none:不配置网络
      • container:容器内网络连通【局限大,用的少,不推荐】
    • 测试

    之前我们直接启动的命令 默认是加上 --net bridge 这个就是我们的 docker0
    docker run -d -P --name tomcat01 --net bridge tomcat
    
    docker0 是默认的,域名不能访问的 我们可以使用 --link 可以打通连接
    
    我们可以自定义一个网络
    --driver bridge  表示使用桥接模式
    --subnet 192.168.0.0/16  表示子网ip   可以分配 192.168.0.2 到 192.168.255.255
    --gateway 192.168.0.1  表示网关
    mynet  表示网络名
    docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
    
    创建好过后我们可以查看一下
    

    在这里插入图片描述

    在这里插入图片描述

    我们可以使用我们创建的自定义网络来启动一个容器
    docker run -d -P --name tomcat-mynet-01 --net mynet tomcat
    docker run -d -P --name tomcat-mynet-02 --net mynet tomcat
    
    再查看 mynet 的元数据就能看见两个容器
    docker network inspect mynet
    

    在这里插入图片描述

    • 那我们为什么要使用自定义的网络呢?
    • 我们再测试一下去 ping 容器,此时直接都可ping通

    在这里插入图片描述

    • 我们不使用 --link 也可以通过容器名来 ping 了
    • 我们自定义的网络,docker都已经帮我们维护好了对应的关系,推荐我们以后这样来使用网络
    • 这样的好处就是 以后我们搭建集群的时候,如mysql何redis 不同的集群可以使用不同的网络,从而保证集群是安全和健康的

    在这里插入图片描述

    网路连通

    • 像前面说的那种情况,假设我的Redis集群中的一个Redis想要访问Tomcat,那该怎么办呢?

    • 两个不同的网段之间直接 ping 是肯定不能通的

    • 那我们可以查看一下 docker network 里面的命令
      在这里插入图片描述

    • 那我们来使用命令测试一下 打通 tomcat-mynet,这里我们先要用正常的方法先创建两个容器 tomcat01 和 tomcat02

    docker run -d -P --name tomcat01 tomcat
    docker run -d -P --name tomcat02 tomcat
    

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    • 就是连通之后,将 tomcat01 放到了 mynet 网络下

    • 就是【一个容器,两个地址】,就好像我们的阿里云服务器那样,一个公网ip,一个私网ip

    • 那我们再来 ping 一下试试
      在这里插入图片描述

    • 想让 tomcat02 能 ping 通 tomcat-mynet,只需将 tomcat02 connect 到 mynet 上即可

    实战:部署 Redis 集群

    在这里插入图片描述

    #1、创建 redis 的网络
    docker network create redis --subnet 172.38.0.0/16
    #查看镜像的元数据
    docker network inspect redis
    
    #2、使用 shell 脚本创建 6 个 redis 容器,并配置
    for port in $(seq 1 6); \
    do \
    mkdir -p /mydata/redis/node-${port}/conf
    touch /mydata/redis/node-${port}/conf/redis.conf
    cat << EOF >/mydata/redis/node-${port}/conf/redis.conf
    port 6379 
    bind 0.0.0.0
    cluster-enabled yes 
    cluster-config-file nodes.conf
    cluster-node-timeout 5000
    cluster-announce-ip 172.38.0.1${port}
    cluster-announce-port 6379
    cluster-announce-bus-port 16379
    appendonly yes
    EOF
    done
    #cd 进入 /mydata/redis 查看
    
    #3、使用配置文件创建 6 个 redis 容器
    docker run -p 6371:6379 -p 16371:16379 --name redis-1 \
    -v /mydata/redis/node-1/data:/data \
    -v /mydata/redis/node-1/conf/redis.conf:/etc/redis/redis.conf \
    -d --net redis --ip 172.38.0.11 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
    
    docker run -p 6372:6379 -p 16372:16379 --name redis-2 \
    -v /mydata/redis/node-2/data:/data \
    -v /mydata/redis/node-2/conf/redis.conf:/etc/redis/redis.conf \
    -d --net redis --ip 172.38.0.12 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
    
    docker run -p 6373:6379 -p 16373:16379 --name redis-3 \
    -v /mydata/redis/node-3/data:/data \
    -v /mydata/redis/node-3/conf/redis.conf:/etc/redis/redis.conf \
    -d --net redis --ip 172.38.0.13 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
    
    docker run -p 6374:6379 -p 16374:16379 --name redis-4 \
    -v /mydata/redis/node-4/data:/data \
    -v /mydata/redis/node-4/conf/redis.conf:/etc/redis/redis.conf \
    -d --net redis --ip 172.38.0.14 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
    
    docker run -p 6375:6379 -p 16375:16379 --name redis-5 \
    -v /mydata/redis/node-5/data:/data \
    -v /mydata/redis/node-5/conf/redis.conf:/etc/redis/redis.conf \
    -d --net redis --ip 172.38.0.15 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
    
    docker run -p 6376:6379 -p 16376:16379 --name redis-6 \
    -v /mydata/redis/node-6/data:/data \
    -v /mydata/redis/node-6/conf/redis.conf:/etc/redis/redis.conf \
    -d --net redis --ip 172.38.0.16 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
    
    #4、创建集群
    先进入 redis-01,redis 官方镜像没有 bash ,要用 sh
    docker exec -it redis-1 /bin/sh
    输入命令 配置集群
    redis-cli --cluster create 172.38.0.11:6379 172.38.0.12:6379 172.38.0.13:6379 172.38.0.14:6379 172.38.0.15:6379 172.38.0.16:6379 --cluster-replicas 1
    显示OK即可
    进入 集群
    redis-cli -c
    查看结点
    cluster nodes
    可以看到三个 master 主机;三个 slave 从机
    #5、测试 我们来设个值,然后存值的那个主机停掉,再看看能不能获取到那个值
    插值
    127.0.0.1:6379> set a b
    -> Redirected to slot [15495] located at 172.38.0.13:6379
    OK
    在宿主机停掉 172.38.0.13 对应的 redis-3
    [root@admin ~]# docker stop redis-3
    redis-3
    再去获取值
    127.0.0.1:6379> get a
    -> Redirected to slot [15495] located at 172.38.0.14:6379
    "b"
    获取成功了!能看到拿到值的地方是 172.38.0.14 ,这个就是 redis-3 的从机,他顶替了 redis-3
    
    #6、我们再使用 cluster nodes 查看结点信息
    可以看到 172.38.0.13 显示 master,fail
    再看到 172.38.0.14 之前是显示 slave 的,但是现在却显示 master,就说明 redis-4 顶替了 redis-3 成为了主机
    

    在这里插入图片描述

    SpringBoot 微服务打包 Docker 镜像

    总共来说就是五个步骤:

    1. 构建 springboot 项目,编写一个controller写一个hello world

    2. 打包应用(这里是 jar 包 / war 包)

    3. 在项目下创建dockerfile(可以直接在 idea 上面写,需要安装一个插件 Docker integration,一般默认有)

    FROM java:8
    
    COPY *.jar /app.jar
    
    CMD ["--server.port=8080"]
    
    EXPOSE 8080
    
    ENTRYPOINT ["java","-jar","/app.jar"]
    
    1. 在这里插入图片描述

    2. 构建镜像
      将项目 jar 包和刚刚编写的 dockerfile 上传到服务器上

    docker build -t tizi6666 .

    等待构建成功

    Successfully built bcb2b2418d6f
    Successfully tagged tizi6666:latest

    1. 启动容器 发布运行

    docker images 查看一下镜像

    docker run -d -P --name tzDemo 镜像id/名字

    1. 测试容器

      docker ps 查看启动的容器

      curl localhost:端口号 可以看到会报错

      curl localhost:端口号/hello 成功输出内容

    使用了docker后,给别人交付一个镜像即可

    针对一个项目的较为简单,预告 如果有很多镜像呢,分别?

    企业级的还需要深造

    Docker Compose容器编排

    docker Swarm(类似k8s 比k8s简单些)集群部署

    CI/CD之 Jenkins DevOps自动的构建/测试软件项目

    ok 总结完毕,学到这里在工作已经足够使用了,有问题还请评论提出,谢谢您的观看和参考

    版权声明:本文为CSDN博主「纸上浅」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/Kobe_k/article/details/106724971

    首先感谢原创者分享的docker总结,个人学习收获也很大。
    本人在学习过程中参考以上原创文章,根据个人学习改动了一些内容。

    展开全文
  • IDEA安装docker详细教程

    2019-11-01 15:36:04
    目录 首先 服务器上的配置(以阿里云服务器为例): 1.服务器设置 2.设置规则 3.配置宝塔 ...4.安装docker并配置阿里仓库(可理解为...dockerDocker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以...
  • 文章目录CentOS7安装DockerDocker简介Docker架构Docker安装流程查看Docker参考文章 Docker简介 Docker 是一个开源的应用容器引擎,基于 Go 语言,并遵从 Apache2.0 协议开源。 Docker 可以让开发者打包他们的应用...
  • Docker详细基础教程

    万次阅读 多人点赞 2020-12-03 09:21:27
    一.Docker介绍 Docker 是一个开源的应用容器引擎,基于 Go 语言 并遵从 Apache2.0 协议开源。 Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上,也...
  • 1.确定虚拟机是centos7及以上版本 cat /etc/redhat-release 2.yum安装gcc相关 yum -y install gcc yum -y install gcc-c++ 3.卸载旧版本 如果虚拟机从来没有安装过docker可以略过此步(注意该...docker-client-l...
  • Docker相关知识了解学习及Cenos 7安装Docker详细教程【附docker常用命令】 一 ,前言   Docker 是一个开源的应用容器引擎,基于 Go 语言 并遵从 Apache2.0 协议开源。   Docker 可以让开发者打包他们的应用以及...
  • centos上安装Docker详细教程

    千次阅读 2018-03-09 22:55:57
    下载centos系统iso文件   去 centos官网 下载你要的版本的centos系统iso文件。 Vmware下载   Vmware下载就不多说,不过,我用的联想正版win10,安装完成后,并不能运行,报错Intel VT-x处于禁用状态。  ...
  • centos7 离线安装Docker详细教程

    千次阅读 2020-09-06 20:22:52
    1、下载所需要的安装包 https://mirrors.aliyun.com/docker-ce/linux/centos/7/x86_64/edge/Packages/ 2、依次安装 rpm -ivh containerd.io-1.2.0-1.2.beta.2.el7.x86_64.rpm rpm -ivh docker-ce-selinux-17.03.3....
  • 阿里云实例 Ubuntu 18.04 64位 安装Docker详细教程 (版本不限) # apt升级 sudo apt-get update # 添加相关软件包 sudo apt-get install \ apt-transport-https \ ca-certificates \ curl \ software-properties-...
  • CentOS7安装docker 官方文档:https://docs.docker.com/install/linux/docker-ce/centos/ 预备工作: 确保自己的系统是CentOS7及以上版本。 可通过下面命令查看系统版本信息 cat /etc/redhat-release 一、安装gcc...
  • Linux离线与在线安装Docker 详细教程

    千次阅读 2020-07-30 14:53:25
    一、在有外网的计算机上准备Docker安装包 1、配置安装源存放路径 [root@www ~]# mkdir -p /root/docker-ce-local && cd /root/docker-ce-local 2、获取createrepo安装包 [root@www docker-ce-local]# yum ...
  • docker容器教程 安装Docker (Installing Docker) 的Ubuntu (Ubuntu) From official docs: https://docs.docker.com/engine/install/ubuntu/ 来自官方文档: https : //docs.docker.com/engine/install/ubuntu/ ...
  • Docker详细教程

    2020-11-12 16:45:49
    # 想安装Docker,需要先将依赖的环境全部下载下来,就像Maven依赖JDK一样 yum -y install yum-utils device-mapper-persistent-data lvm2 1.2 指定Docker源 # Docker的源在国外,下载镜像的速度慢,指定阿里云镜像...
  • docker安装以及配置镜像加速 本文使用 Linux 环境教大家如何基于 CentOS 安装 Docker 及配置镜像加速。 相关链接 Docker 官网:https://www.docker.com. Github Docker 源码:https://github.com/docker/docker-ce. ...
  • docker微服务教程

    2019-01-02 14:09:25
    docker教程详细讲述docker的使用,省去Linux下载,安装配置的麻烦,直接使用容器就好,你值得拥有 (●'◡'●)
  • Centos7下安装Docker详细安装教程

    万次阅读 多人点赞 2019-09-04 09:42:47
    一,Docker简介 百科说:Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间...
  • ubuntu环境: Distributor ID: Ubuntu Description: Ubuntu 16.04.2 LTS Release: 16.04 Codename: xenial 以下命令可查看ubuntu版本: ...B站狂神docker教程视频:https://www.bilibili.com/vid...
  • (可以根据自己需要的环境方法下载docker软件,这里演示的是ubuntu上的docker安装教程) centos-8版本的安装教程:https://blog.csdn.net/weixin_50999155/article/details/119580762 目录 第一步、卸载旧版本...
  • Docker详细使用教程

    2020-05-11 21:30:27
    Docker 01-主要内容 初识 Docker Docker 命令 Docker 容器数据卷 Dockerfile Docker 应用部署 Docker 服务编排 Docker 私有仓库 Docker相关概念 02-初识docker-docker概述 分析: ​ 把环境一起给打包起来 ​ 操作...
  • 一.Docker介绍 Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的 Linux或Windows 机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间...
  • Docker面试: 1、从图标开始讲起,鲸鱼、集装箱、互相隔离;思想就来自于集装箱; 2、vm、docker小巧,几M,方便 3、Go语言开发 clear 清理当前窗口 环境uname -r 3.10.0-862.9.1.el7.x86_64 服务器信息 cat /...
  • Docker入门详细教程

    2021-09-02 14:38:59
    目录 Docker的介绍 Docker的思想 集装箱 ...Docker的组成 ...Docker的运行机制 ...Docker运行镜像的流程 ...Docker常用命令 ...Docker自定义镜像 ...然后慢慢等待拉取下载完成,因为是从官网拉取,所以有点慢. ..
  • Ubuntu下Docker详细安装教程

    千次阅读 2018-10-31 11:54:44
    为什么要用docker,只有用过的人才知道有多爽,研究了几天,在centos下安装总会出现各种问题,新手建议使用Ubuntu,用下面的步骤安装成功,亲历为证。 以下内容根据 官方文档 修改而来。 如果你过去安装过 ...
  • 非常详细Docker学习教程

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 7,871
精华内容 3,148
关键字:

下载docker详细教程