Docker 基础

Starter

一种依赖于Linux内核,操作系统级别的虚拟化方案 (即容器技术),Go语言开发,基于Apache2.0开源授权协议发行

(官网](https://www.docker.com)

  1. 虚拟化技术:

    • 硬件级虚拟化,eg:VM(虚拟机)
    • 操作系统级虚拟化 eg:Docker
    • vm-vs-docker1 vm-vs-docker2
  2. Docker思想:

    • 集装箱
    • 标准化-运输方式,存储方式,API接口
    • 隔离
  3. Docker解决问题:

    • 我本地运行没问题啊!
    • 系统好卡,哪个哥们又写死循环了?!
    • 双十一来啦,服务器撑不住啦!

Linux内核特性

  1. Namespaces 命名空间 :隔离资源

    • PID 进程
    • NET 网络
    • IPC 跨进程通讯(InterProcess Communication)
    • MNT 挂载点(Mount)
    • UTS 内核和版本标识(Unix Timesharing System)
  2. CGroups 控制组 Control Group : 分配并管理隔离资源

    • 文件系统隔离:在Docker中 ,每个Container有自己的root文件系统
    • 进程隔离:在Docker中 ,每个Container运行在自己的进程环境
    • 网络隔离:在Docker中 ,Container间的虚拟网络接口和IP地址都是分开的
    • 资源隔离和分组: 在Docker中 ,使用cgroups将CPU和内存之类的资源独立的分配给每个Container
  3. Union FS: 联合文件系统 Union File System:文件系统层叠

    • 在Docker中,镜像即由多个文件系统(只读层)叠加而成,容器即为加载在只读镜像层上(镜像栈顶部)的一个读写层
    • 注:
      • 当改变镜像或升级程序版本时,只是一个新的层被添加或升级了,不用重新发布整个镜像,只需要升级,层使得分发 Docker 镜像变得简单和快速
      • 在容器中修改现有已存在文件,会将该文件将会从只读层复制到读写层,该文件的只读版本仍然存在,只是被读写层中该文件的副本所隐藏

docker-core

Docker架构和组件

docker-component

Docker 架构(CS架构):

  • Client:一个命令行工具,可发送Docker命令到Server -- 通过HTTP协议与Docker Server交互
  • Server:一直运行在后台的守护进程(Docker daemon),接收Client发送的命令并执行 -- 其中内嵌了一个Web Server

Docker 组件:

  • 容器(Container)
    • Docker运行的最小单位(image启动后产生的instance)
    • 类似一个轻量级的虚拟机:每个容器拥有独立的root文件系统,网络服务,进程服务等,容器间互补干扰
  • 镜像(Image)
    • 用于构建容器(打包好的环境,一堆文件而已,启动后产生的instance即为container)
    • 层叠的只读文件系统,容器的基石/模版
    • 可在本地创建,可推送(Push)到仓库(Registry),可从仓库(Registry)拉取(Pull)到本地
  • 仓库(Registry)
    • 用于存放镜像(方便传输image)
    • 公有仓库
      • eg:官方提供的Docker Hub,网易蜂巢c.163.com,...
      • 远程仓库,速度等受限,在国内可使用Docker加速器(eg:DaoCloud ,阿里云 )方便下载镜像
    • 私有仓库
      • eg:本地仓库(通过docker images查看的就是本地registry下的镜像),局域网自行搭建的仓库,...

镜像 vs 容器

关系好比:

  • 代码和启动运行这段代码的程序(code vs app);
  • 模版和实例( templete vs instance)

  • 镜像(Image):

    • 容器的基石
    • 层叠的只读文件系统
    • 联合加载(Union Mount) image
  • 容器(Container):

    • 通过镜像启动
    • 启动和执行阶段
    • 写时复制(Copy on Write) container
  • 注:

    • 已建立的image的层是只读的,image启动的container,是一个新层,且是可读写的
    • 若要对image中的文件进行修改,则会copy一份到最上层,即container层 image-container
  • 应用:

    • 在容器中开发,以容器的形式交付和分发 (Dockerize:将应用程序和环境打包成一个image),这样开发测试生产都使用相同的环境,避免额外的部署和调试上的开销,有效缩减产品上线周期。
    • 推荐单个容器使用一个应用或进程,形成一个分布式的应用程序模型,高内聚,低耦合,单一任务(避免不同服务间的影响)

安装配置

Docker 是一个开源的商业产品,有两个版本:社区版(Community Edition,缩写为 CE)和企业版(Enterprise Edition,缩写为 EE)

Docker CE 的安装官方文档:

注: Docker有些操作需要sudo 权限,可使用sudo -i 切换

Windows下安装配置

Refer: Docker Toolbox for Windows 之安装二三事

  1. 下载安装:

    • Windows10/WindowsServer2016 可使用 Docker for Windows Installer.exe,其他使用DockerToolbox.exe(会虚拟一个Linux的环境)
    • 这里使用 DockerToolbox.exe,安装到 C:\Soft\Docker Toolbox
    • 默认docker-machine workspace 为C:\Users\<your-user>\.docker =>即 C:\Users\jinc\.docker
    • 可在cmd.exe中查看安装的各个版本信息:

        C:\Users\jinc>docker --version
        Docker version 17.03.1-ce, build c6d412e
      
        C:\Users\jinc>docker-machine --version
        docker-machine version 0.10.0, build 76ed2a6
      
        C:\Users\jinc>docker-compose --version 
        docker-compose version 1.11.1, build 7afaa436
      
  2. 运行 Docker QuickStart Terminal 终端 ( will install docker machine 'default' at first time )

    • docker-machine (默认情况下,docker-machine 会自动建立一个名为 default的 machine/engine)

                                ##         .
                          ## ## ##        ==
                       ## ## ## ## ##    ===
                   /"""""""""""""""""\___/ ===
              ~~~ {~~ ~~~~ ~~~ ~~~~ ~~~ ~ /  ===- ~~~
                   \______ o           __/
                     \    \         __/
                      \____\_______/
      
        docker is configured to use the default machine with IP 192.168.99.100
        For help getting started, check out the docs at https://docs.docker.com
      
        Start interactive shell
      
        jinc@JINC-CN MINGW64 ~
        $ docker-machine version
        docker-machine.exe version 0.10.0, build 76ed2a6
      
        $ docker-machine ls
        NAME       ACTIVE   DRIVER       STATE     URL                         SWARM   D OCKER        ERRORS
        default    *        virtualbox   Running   tcp://192.168.99.100:2376           v 17.04.0-ce
      
        $ docker-machine ip
        192.168.99.100
      
        $ docker-machine status
        Running
      
        $ docker-machine active
        default
      
        $ docker-machine env default
        export DOCKER_TLS_VERIFY="1"
        export DOCKER_HOST="tcp://192.168.99.100:2376"
        export DOCKER_CERT_PATH="C:\Users\jinc\.docker\machine\machines\default"
        export DOCKER_MACHINE_NAME="default"
        export COMPOSE_CONVERT_WINDOWS_PATHS="true"
        # Run this command to configure your shell:
        # eval $("C:\Soft\Docker Toolbox\docker-machine.exe" env default)
      
    • docker version

        $ docker version
        time="2018-02-24T11:42:38+08:00" level=info msg="Unable to use system certificat
        e pool: crypto/x509: system root pool is not available on Windows"
        Client:
         Version:      17.03.1-ce
         API version:  1.27
         Go version:   go1.7.5
         Git commit:   c6d412e
         Built:        Tue Mar 28 00:40:02 2017
         OS/Arch:      windows/amd64
      
        Server:
         Version:      17.04.0-ce
         API version:  1.28 (minimum version 1.12)
         Go version:   go1.7.5
         Git commit:   4845c56
         Built:        Wed Apr  5 18:45:47 2017
         OS/Arch:      linux/amd64
         Experimental: false
      
    • docker info
        $ docker info
        time="2018-02-24T11:42:42+08:00" level=info msg="Unable to use system certificat
        e pool: crypto/x509: system root pool is not available on Windows"
        Containers: 2
         Running: 0
         Paused: 0
         Stopped: 2
        Images: 1
        Server Version: 17.04.0-ce
        Storage Driver: aufs
         Root Dir: /mnt/sda1/var/lib/docker/aufs                                # Note
         Backing Filesystem: extfs
         Dirs: 5
         Dirperm1 Supported: true
        Logging Driver: json-file
        Cgroup Driver: cgroupfs
        Plugins:
         Volume: local
         Network: bridge host macvlan null overlay
        Swarm: inactive
        Runtimes: runc
        Default Runtime: runc
        Init Binary:
        containerd version: 422e31ce907fd9c3833a38d7b8fdd023e5a76e73
        runc version: 9c2d8d184e5da67c95d601382adf14862e4f2228
        init version: 949e6fa
        Security Options:
         seccomp
          Profile: default
        Kernel Version: 4.4.59-boot2docker
        Operating System: Boot2Docker 17.04.0-ce (TCL 7.2); HEAD : c69677f - Thu Apr  6
        16:26:16 UTC 2017
        OSType: linux
        Architecture: x86_64
        CPUs: 1
        Total Memory: 995.8 MiB
        Name: default
        ID: OH5Z:NNKL:4AGQ:EE7H:RRS2:7BHC:Z245:XPIT:QRE7:CZAW:SKFT:LH4W
        Docker Root Dir: /mnt/sda1/var/lib/docker                                # Note
        Debug Mode (client): false
        Debug Mode (server): true
         File Descriptors: 16
         Goroutines: 25
         System Time: 2018-02-24T03:42:42.456181611Z
         EventsListeners: 0
        Https Proxy:
        Registry: https://index.docker.io/v1/
        Labels:
         provider=virtualbox
        Experimental: false
        Insecure Registries:
         127.0.0.0/8
        Live Restore Enabled: false
      
  3. Enter machine ( 进入虚拟主机,即可运行的docker环境 )

    • 方式一:在Docker QuickStart Terminal 终端 或 cmd.exe终端输入docker-machine ssh default
    • 方式二(recommend):使用SSH远程访问工具,eg:Putty.exe( Host:192.168.99.100 ; Port: 22 ; Connection type: SSH,Username/password: docker/tcuser)
    • Note:可安装FTP工具FileZilla来上传下载文件到docker虚拟机(使用SFTP协议)
  4. 使用docker(eg: run to test pulling an image from Docker Hub and starting a container)

     docker run hello-world
     docker run -it ubuntu bash
     docker run -d -p 80:80 --name webserver nginx
     curl http://localhost
    

安装总结:

  1. 下载安装DockerToolbox.exe
  2. 启动'Docker QuickStart Terminal' 终端 (第一次会自动安装machine:default ,可使用docker-machine ls 查看已安装的machine)
  3. cmd.exeDocker QuickStart Terminal终端输入docker-machine ssh default进入docker运行环境(或者使用Putty工具连接登录docker-machine IP,username/password: docker/tcuser)
  4. 正式使用docker时,保证docker主机是running的,可通过docker-machine status 查看,若未启动,可使用docker-machine start启动

Mac环境下安装配置

下载Docker for Mac,安装提示操作安装即可 启动时不需要再使用dokcer-machine设定启动的默认的环境,省去了使用virtualbox的过程(享受和在linux下使用docker一样的体验)

Refer Mac环境下Docker的初识和运用

安装后查看:

  • 检查版本
      $ docker -v
      Docker version 1.12.1, build 6f9534c
    
  • 安装路径
      $ which docker
      /usr/local/bin/docker
    
  • 详细信息(注意Root Dir和Docker Root Dir)
      $ docker info
      Containers: 5
      Running: 0
      Paused: 0
      Stopped: 5
      Images: 5
      Server Version: 1.12.1
      Storage Driver: aufs
      Root Dir: /var/lib/docker/aufs                                                # Note
      Backing Filesystem: extfs
      Dirs: 21
      Dirperm1 Supported: true
      Logging Driver: json-file
      Cgroup Driver: cgroupfs
      Plugins:
      Volume: local
      Network: null overlay host bridge
      Swarm: inactive
      Runtimes: runc
      Default Runtime: runc
      Security Options: seccomp
      Kernel Version: 4.4.20-moby
      Operating System: Alpine Linux v3.4
      OSType: linux
      Architecture: x86_64
      CPUs: 2
      Total Memory: 1.953 GiB
      Name: moby
      ID: WD5T:HQMU:CKW6:WIHN:HUDK:4RSL:FZ5Q:XU72:SZBY:3OOV:PZ6Z:SYXQ
      Docker Root Dir: /var/lib/docker                                            # Note
      Debug Mode (client): false
      Debug Mode (server): true
      File Descriptors: 16
      Goroutines: 27
      System Time: 2018-03-10T03:20:38.356925515Z
      EventsListeners: 1
      No Proxy: *.local, 169.254/16
      Registry: https://index.docker.io/v1/
      Insecure Registries:
      127.0.0.0/8
    
  • 配置:可直接通过图形化界面配置

docker-machine

一个在“本地”或者“云平台”上 管理 docker-engine 的工具

是在docker-host(物理机器)上面管理 docker-engine的工具,所以它有属于它自己的一组CLI(command line interface)

  1. 常用命令:

    • show machine info:
        docker-machine ip
        docker-machine ls
        docker-machine active
        docker-machine status <machine_name>   # 不加arg,则显示默认machine的信息
        docker-machine inspect <machine_name>  # 不加arg,则显示默认machine的信息,只可以查看Running的machine
        docker-machine env <machine_name>      # 不加arg,则显示默认machine的信息,只可以查看Running的machine
      
    • create/start/stop/restart/rm docker-machine :
        docker-machine create -d virtualbox mydocker     # -d 即 --driver
        docker-machine start mydocker
        docker-machine stop mydocker
        docker-machine rm mydocker
      
    • enter machine:
        docker-machine ssh mydocker
      
  2. 配置:

    • 配置加速器

      • 为已存在的docker-machine配置
          > docker-machine ssh mydocker
          > vi /var/lib/boot2docker/profile
          EXTRA_ARGS='
               --label provider=virtualbox
               --registry-mirror <url>
          '
          > exit
          > docker-machine restart mydocker
        
      • docker-machine create时配置
          > docker-machine create -d virtualbox --engine-registry-mirror=<url> mydocker
        
      • 注:常用的加速器(下面XXX需要更换成自己的加速地址)
        • DaoCloud url:http://XXX.m.daocloud.io
        • 阿里云 ur: https://XXX.mirror.aliyuncs.com
    • 配置代理

      • 为已存在的docker-machine配置

          > docker-machine ssh mydocker
          > vi /var/lib/boot2docker/profile
          EXTRA_ARGS='
          --label provider=virtualbox
        
          '
          CACERT=/var/lib/boot2docker/ca.pem
          DOCKER_HOST='-H tcp://0.0.0.0:2376'
          DOCKER_STORAGE=aufs
          DOCKER_TLS=auto
          SERVERKEY=/var/lib/boot2docker/server-key.pem
          SERVERCERT=/var/lib/boot2docker/server.pem
        
          export "HTTPS_PROXY=http://example.com:8080"
        
          > exit
          > docker-machine restart mydocker
        
      • docker-machine create时配置
          > docker-machine create -d virtualbox \
          --engine-env HTTP_PROXY=http://example.com:8080 \
          --engine-env HTTPS_PROXY=https://example.com:8080 \
          --engine-env NO_PROXY=example2.com \
          mydocker
        
    • 修改docker client连接的默认主机

        # 设置环境变量: 将mydocker主机作为docker deamon(服务端)
        > eval $(docker-machine env mydocker)
      
        # 查看主机列表:mydocker主机Active状态为'*'
        > docker-machine ls
      

常见错误

  1. Error checking TLS connection : 当出现如下错误时,可执行重新生成证书 (regenerate certs)

     # Error checking TLS connection: Error checking and/or regenerating the certs: There was an error validating certificates for host "192.168.99.100:2376": x509: certificate is valid for 192.168.99.101, not 192.168.99.100
     # ...
     > docker-machine regenerate-certs mydocker
     > docker-machine restart mydocker
    
  2. For x509 IP SANs error : use '--no-proxy' when set env in cmd console :

     > docker ps -a
     time="2017-04-11T14:34:16+08:00" level=info msg="Unable to use system certificate pool: crypto/x509: system root pool is not available on Windows"
     error during connect: Get https://192.168.99.101:2376/v1.27/containers/json: x509: cannot validate certificate for 192.168.99.101 because it doesn't contain any IP SANs
    
     # 设置当前的环境是与哪个主机通信
     > docker-machine env mydocker --no-proxy
     > @FOR /f "tokens=*" %i IN ('docker-machine env mydocker --no-proxy') DO @%i
    
     > docker ps -a
     time="2017-04-11T16:14:34+08:00" level=info msg="Unable to use system certificat e pool: crypto/x509: system root pool is not available on Windows"
     CONTAINER ID        IMAGE               COMMAND             CREATED      STATUS              PORTS               NAMES
    
  3. docker-machine restart lost data issue

镜像 Image

把应用程序及其依赖打包入一个二进制文件,作为容器的模板(实际开发中,一个 image 文件往往通过继承另一个 image 文件,加上一些个性化设置而生成)

标识

  • Repository:仓库下的镜像(显示镜像名imageName,注意:镜像名可能不能唯一确定一个镜像)
  • Tag:每个镜像可以打上一个或多个Tag,默认为latest,一般可以为version信息 (Repository:Tag 唯一标识一个镜像)
  • Image Id:唯一,64位字符,通常只用前12个字符就可以了

常用命令

docker images [options]                        # 列出镜像
docker images [options] <imageName>[:tag]      # options:
                                               #     -a,--all = false
                                               #     -f,--filter = []
                                               #     --no-trunc = false
                                               #     -q,--quiet = false (Only show numeric IDs)

docker inspect [options] <imageName>[:tag]     # 查看镜像
docker inspect [options] <imageId>             # options:
                                               #     -f,--format = ""

docker run [options] <image>                   # 启动镜像(即生成运行容器,若本地没有此image,则会先从远程下载image)

docker rmi [options] image[image...]           # 删除镜像
                                               # options:
                                               #    -f,--force = false ( Force removal of the image )
                                               #    --no-prune = false ( Do not delete untagged parents )

docker search <image>                          # 搜索远程仓库镜像
docker pull <imageName>[:tag]                  # 从远程仓库拉取镜像
docker push <imageName>[:tag]                  # 推送镜像到远程仓库
                                               # 默认使用官网仓库https://hub.docker.com,
                                               # 速度慢可使用daocloud提供的加速器

示例:

$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
cj/centos           latest              d9ae4dc53b8e        14 months ago       473.4 MB
centos              latest              67591570dd29        14 months ago       191.8 MB
ubuntu              latest              104bec311bcd        14 months ago       129 MB
nginx               latest              e43d811ce2f4        16 months ago       181.5 MB
hello-world         latest              c54a2cc56cbb        20 months ago       1.848 kB

$ docker images centos
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
centos              latest              67591570dd29        14 months ago       191.8 MB

$ docker images centos:latest
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
centos              latest              67591570dd29        14 months ago       191.8 MB

$ docker images -q
d9ae4dc53b8e
67591570dd29
104bec311bcd
e43d811ce2f4
c54a2cc56cbb
$ docker inspect ubuntu:14.04
$ docker inspect d9ae4dc53b8e

$ docker rmi ubuntu:12.04 ubuntu:precise
$ docker rmi d9ae4dc53b8e
$ docker rmi $(docker images -q ubuntu)

$ docker pull ubuntu
$ docker pull redis:2.8.19

构建镜像

  1. 方式一:使用Container构建镜像

     $ docker commit --help
    
     Usage:    docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
     Create a new image from a container's changes
    
     Options:
       -a, --author string    Author (e.g., "John Hannibal Smith <hannibal@a-team.com>")
       -c, --change value     Apply Dockerfile instruction to the created image (default [])
           --help             Print usage
       -m, --message string   Commit message
       -p, --pause            Pause container during commit (default true)
    
     # 示例:
     # docker commit [options] <containerId> <newImageName>:[tag]
     $ docker commit -m 'fun' 17add7bbc58c nginx-fun
    
  2. 方式二:依赖image产生新的镜像(类似copy)

     docker tag hello-world cj/hello-world        # 依赖hello-world镜像产生新的cj/hello-world镜像(类似复制)
    
  3. 方式三:使用Dockerfile构建镜像 Dockerfile reference

     $ docker build --help
    
     Usage:    docker build [OPTIONS] PATH | URL | -
     Build an image from a Dockerfile
    
     Options:
           --build-arg value         Set build-time variables (default [])
           --cgroup-parent string    Optional parent cgroup for the container
           --cpu-period int          Limit the CPU CFS (Completely Fair Scheduler) period
           --cpu-quota int           Limit the CPU CFS (Completely Fair Scheduler) quota
       -c, --cpu-shares int          CPU shares (relative weight)
           --cpuset-cpus string      CPUs in which to allow execution (0-3, 0,1)
           --cpuset-mems string      MEMs in which to allow execution (0-3, 0,1)
           --disable-content-trust   Skip image verification (default true)
       -f, --file string             Name of the Dockerfile (Default is 'PATH/Dockerfile')
           --force-rm                Always remove intermediate containers
           --help                    Print usage
           --isolation string        Container isolation technology
           --label value             Set metadata for an image (default [])
       -m, --memory string           Memory limit
           --memory-swap string      Swap limit equal to memory plus swap: '-1' to enable unlimited swap
           --no-cache                Do not use cache when building the image
           --pull                    Always attempt to pull a newer version of the image
       -q, --quiet                   Suppress the build output and print image ID on success
           --rm                      Remove intermediate containers after a successful build (default true)
           --shm-size string         Size of /dev/shm, default value is 64MB
       -t, --tag value               Name and optionally a tag in the 'name:tag' format (default [])
           --ulimit value            Ulimit options (default [])
    
     # 示例:
     # docker build -t <newImageName>[:tag] <DockerfilePath>
     docker build -t myrepo/myapp /tmp/test1
    
    • 执行过程:
      1. 读取指定路径下(包括子目录)的 Dockerfile
        • 会将该路径下所有内容发送给 Docker Server来创建镜像
        • 建议放置 Dockerfile 的目录为空目录(也可通过 .dockerignore 文件指定忽略文件和路径)
      2. 按照Dockerfile中的指令顺序依次执行
        • 缓存:每执行一次指令, Docker 会寻找是否有存在的镜像缓存可复用,如果没有则创建新的镜像(build时--no-cache=true则禁用)
        • 镜像的中间层(镜像分层)
      3. 可使用 docker history <image> 查看镜像的构建过程 Dockerfile

Dockerfile

Structure(基本格式):

#Comment
INSTRUCTION argument

Instructure (指令):

FROM <imageName>[:tag]                 # 指定新镜像的baseImage(必须是第一条非注释指令)

MAINTAINER <author> <email>          # 说明新镜像的维护者信息

ENV <key> <value>                    # 指定环境变量( 可在Dockerfile的后续代码中使用,并在容器运行时保持)
ENV <key>=<value> ...

USER <username>                      # 指定运行容器时的用户名或 UID,后续的 RUN 也会使用指定用户
USER <uid>

WORKDIR <path>                       # 设置工作目录(绝对路径或相对路径都可 )
                                     # 设置后,后续的RUN,CMD,ENTRYPOINT等操作都将在这个目录下完成

ADD/COPY <src> <dest>                 # 拷贝当前构建环境下的文件或目录到容器
                                     # 地址末尾/,则是文件夹,无/则是文件
                                     #  ADD的src:Dockerfile所在目录的一个相对路径/URL/打包压缩文件(自动解压成文件目录)
                                     #  COPY的src:Dockerfile所在目录的一个相对路径,不能是URL,也不会自动解压打包压缩的文件

RUN/CMD/ENTRYPOINT <cmd> <arg1> <arg2> ...    # 执行命令 (Shell模式:自动调用Shell,即自动在命令前面追加/bin/sh -c)
RUN/CMD/ENTRYPOINT ["cmd","arg1","arg2",...]  # 执行命令 (Exec模式-推荐:不会调用任何Shell,即不会进行变量替换)
                                              # 对比:
                                              #   RUN
                                              #      构建镜像时执行,即docker build命令时执行
                                              #      可以有多条,依次执行
                                              #   CMD/ENTRYPOINT
                                              #      运行容器时执行,即docker run命令时执行
                                              #      后面的覆盖前面
                                              #      docker run [--entrypoint ...] <image> [cmd] 可覆盖Dockerfile中的
                                              #   ENTRYPOINT - 往往用于设置容器启动后的第一个命令,往往是固定的
                                              #   CMD - 往往用于设置容器启动的第一个命令的默认参数,往往是可以是变化的


ONBUILD <INSTRUCTION>                # 镜像触发器,当此镜像被其他镜像作为baseImage,其他镜像build时执行的指令

VOLUME ["path1","path2",...]         # 添加一个数据卷(挂载点)
                                     # 同docker run -v <containerPath> -v <containerPath> ...

EXPOSE <port1> <port2> ...           # 暴露容器端口号(隐式暴露),供宿主机和其他容器使用
                                     # 需要在 docker run 的时候使用 -P/p 选项(显式暴露)才生效

示例:

  1. 编写Dockerfile (Space/node01):

     # 设置basic image
     FROM node:latest
     # 把容器编码设置为C.UTF-8 支持中文
     ENV LANG C.UTF-8
     # Config npm proxy
     RUN npm config set proxy http://cn-proxy.jp.oracle.com:80/
     # 将当前项目中的index.js,package.json 拷贝到image的/app目录下
     COPY index.js package.json /app/
     # 将当前项目中的public目录拷贝到image的/app目录下
     COPY public/ /app/public/
     # 切换到/app目录下
     WORKDIR /app
     # 执行命令并提交到image (RUN = docker run + docker commit)
     RUN npm install && npm cache clean --force
     # 设定image启动时的预设指令
     CMD node index.js
    
  2. 构建运行:

     cd space/node01
     docker build -t node_test01 .
     docker run -it node_test01 /bin/bash
     docker run -d -p 1337:1337 node_test01
    
  3. 测试结果

     http://192.168.99.100:1337
     http://192.168.99.100:1337/
    
  4. 再次进入容器

     # docker attach <containerId>
     # docker exec -it <containerId> /bin/bash
     docker exec -it db1da18b6479 /bin/bash
    

容器 Container

  • Docker 根据 image 文件生成容器的实例。同一个 image 文件,可以生成多个同时运行的容器实例
  • image 文件生成的容器实例,本身也是一个文件,称为容器文件。
  • 一旦容器生成,就会同时存在两个文件: image 文件和容器文件。且关闭容器并不会删除容器文件,只是容器停止运行而已

常用命令:

docker run [options] <image> [cmd] [arg...]        # 启动一个容器
                                                   # 容器运行成功后,会产生一个64位的容器ID,作为容器的唯一标示
                                                   # options:
                                                   #     -d  表示后台运行(执行完cmd,则自动退出并停止容器)
                                                   #     -it 启动交互式容器
                                                   #         exit 退出并停止容器
                                                   #         Ctrl+P/Q 退出交互模式,改后台运行(再次进入:docker attach <container>)
                                                   #     -e  设置环境参数(env)
                                                   #     -p  指定映射容器的某些端口(--public=[])
                                                   #            -p containerPort
                                                   #            -p hostPort:containerPort
                                                   #            -p ip:containerPort
                                                   #            -p ip:hostPort:containerPort
                                                   #            -p 7060-7080:8060-8080 (一个范围,个数需匹配)
                                                   #     -P  映射容器暴露的所有端口(--public-all=true)
                                                   #         将Dockerfile中EXPOSE所暴露的所有端口分别映射到宿主机的随机端口,
                                                   #         每次启动或重启容器时端口都可能有所不同
                                                   #     --name 为启动容器起个名字

docker exec [option] <container> [cmd] [arg...] # 为已启动的容器启动新进程
                                                # options(同docker run):
                                                #    -d 后台运行,cmd运行完即退出                   
                                                #    -it 交互式

docker ps [options]                             # 列出容器(默认列出active的容器)
                                                # options:
                                                #    -a:all 列出所有
                                                #    -l:latest 列出最新创建的一个容器
                                                #    -q: quite ( Only show numeric IDs)

docker inspect [options] <container>            # 查看容器的详细信息
                                                # options:                                
                                                #     -f,--format = ""

docker top <container>                          # 查看容器内进程
docker logs [option] <container>                # 查看容器日志
                                                # options:
                                                #    -f : --follow=true 一直跟踪logs的变化并返回结果
                                                #    -t : --timestamps=true  在返回的结果上加上时间戳
                                                #    --tail <n>:  返回结尾处n条日志,0 表示最新的日志(默认返回所有)


docker stop <container>                         # 停止容器(发送一个结束信号给容器,等待容器停止)
docker kill <container>                         # 杀死容器(直接停止)
docker start [-i] <container>                   # 重启停止的容器(-i : 交互式)
docker rm [-f] <container>                      # 删除容器(-f : force 强制删除运行中的容器)

示例:

$ docker run -d nginx
5385902c48cf05359617933cc75bfa5d4651d199f6fd2651134d6e7d4a57d67e

$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
5385902c48cf        nginx               "nginx -g 'daemon off"   4 seconds ago       Up 3 seconds        80/tcp, 443/tcp     backstabbing_bhabha

$ docker ps -a -f "name=backstabbing_bhabha"
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
5385902c48cf        nginx               "nginx -g 'daemon off"   4 seconds ago       Up 3 seconds        80/tcp, 443/tcp     backstabbing_bhabha

$ docker ps -a --format '{{.Names}}'
backstabbing_bhabha

$ docker exec -it 5385902c48 bash
root@5385902c48cf:/# ls
bin  boot  dev    etc  home  lib    lib64  media  mnt  opt    proc  root  run  sbin  srv  sys  tmp  usr  var
root@5385902c48cf:/# ps -ef
UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 05:05 ?        00:00:00 nginx: master process nginx -g daemon off;
nginx        5     1  0 05:05 ?        00:00:00 nginx: worker process
root         6     0  0 05:06 ?        00:00:00 bash
root        13     6  0 05:06 ?        00:00:00 ps -ef
root@5385902c48cf:/# exit
exit

$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED              STATUS              PORTS               NAMES
5385902c48cf        nginx               "nginx -g 'daemon off"   About a minute ago   Up About a minute   80/tcp, 443/tcp     backstabbing_bhabha

$ docker stop 5385902c48cf
5385902c48cf

$ docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                      PORTS               NAMES
5385902c48cf        nginx               "nginx -g 'daemon off"   21 minutes ago      Exited (0) 18 seconds ago                       backstabbing_bhabha

数据管理

数据卷 & 数据卷容器

数据的持久化/共享:

  1. 数据卷 (Data Volume):

    • 在容器启动时初始化,独立于容器的生存周期,为一个或多个容器提供数据访问
    • 一直存在,即使挂载该数据卷的容器已经被删除
    • 注:Volume 即目录或文件,它可绕过默认的联合文件系统(UFS:Union File System),以正常的文件或目录形式存在于宿主机上,类似linux下的挂载(mount)
      • 数据卷可以在容器之间共享和重用
      • 数据卷数据改变是直接修改的
      • 数据卷是持续性的,直到没有容器使用它们 Volume
  2. 数据卷容器(Data Volume Container):

    • 挂载数据卷的容器即为数据卷容器
    • 其他容器可通过挂载这个容器实现数据共享(这时这些容器都可称为数据卷容器) Volume Container

常用命令

> docker volume --help
...
Commands:
  create      Create a volume
  inspect     Display detailed information on one or more volumes
  ls          List volumes
  prune       Remove all unused volumes
  rm          Remove one or more volumes

管理

  1. 创建:

    • 方式一:启动容器时添加数据卷 docker run -v [<hostPath>:]<containerPath>[:<privilege>] ...

        # 使用默认主机目录
        docker run -v /web -it ubuntu --name vbase /bin/bash
      
        # 明确主机目录(bind-mounts)
        docker run -v /host/web:/app/web:ro -it ubuntu --name vbase /bin/bash
      
      • -v--volume,可使用多个
      • 默认使用主机目录/var/lib/docker
      • 主机目录/容器目录不存在时会被自动创建
      • 默认privilege是rw,可读写
    • 方式二:在Dockerfile中配置VOLUME ["<containerPath1>","<containerPath2>,..."] (效果同方式一的不指定hostPath)

        > vi Dockerfile
        ...
        # VOLUME /myvol 
        VOLUME ["/var/www", "/var/log/apache2", "/etc/apache2"]
      
        > docker run xxx                                            # 启动容器时会初始化数据卷
      
    • 方式三:启动容器时挂载数据卷容器 docker run --volumes-from <volumeContainer> ...

        # 创建数据卷容器vbase
        docker create -v /web --name vbase centos
      
        # vbase为已创建的数据卷容器
        docker run --volumes-from vbase -it ubuntu --name vtest01 /bin/bash
        docker run --volumes-from vbase -it ubuntu --name vtest02 /bin/bash
      
        # 可以继承其它挂载了数据卷的容器
        docker run --volumes-from vtest02 -it ubuntu -name vtest03 /bin/bash
      
      • -volumes-from可使用多个
      • 不论数据卷容器是否运行,都可挂载
  2. 查看:

     # 列出所有数据卷
     docker volume ls
    
     # 通过docker inspect查看容器数据卷对应的宿主机路径
     docker inspect <container>
     docker inspect --format="{{ .Volumes }}" <container>
    
  3. 删除:

     # Remove all unused volumes
     docker volume prune
    
     # Remove one or more volumes
     docker volume rm [OPTIONS] VOLUME [VOLUME...]
    
     # 容器启动时设置运行停止时就自动删除容器以及容器所挂载的volume
     docker run --rm ...   
    
     # Remove the volumes associated with the container
     # 删除容器时,同时也删除挂载的volume
     # 注:如果直接使用docker rm 删除容器,可能会有很多孤立的Volume仍占用着空间(eg:在/var/lib/docker/vfs/dir目录中遗留很多不明目录),所以使用docker rm -v 更安全            
     docker rm -v <container>
    
  4. 应用示例:数据备份和还原

     # 启动一个容器挂载vbase:/web,备份:将/web下的内容打包到/backup
     docker run --rm --volumes-from vbase -v /backup:/backup ubuntu tar cvf /backup/web.tar /web
    
     # 启动一个容器挂载vtest:/test,还原:将/backup下备份的数据还原到容器/test下
     docker run --rm --volumes-from vtest -v /backup:/backup ubuntu tar xvf /backup/web.tar -C /test
    

网络管理

管理与宿主机的通信,容器与容器间的通信

  1. 命令:

     > docker network -- help
     ...
     Commands:
     connect      Connect a container to a network
     create       Create a network disconnect Disconnect a container from a network
     inspect      Display detailed information on one or more networks
     ls           List networks
     rm           Remove one or more networks
    
  2. 查看网络(默认有三个 ):

     > docker network ls
     NETWORK ID          NAME                DRIVER              SCOPE
     bd3defcfcc1c        bridge              bridge              local     
     b623769af9b8        host                host                local
     1d16147fa052        none                null                local
    
    • bridge: 容器的默认网络,有独立的network namespace(IP,Port),配置后可与宿主机通信从而与互联网互联互通(配置端口映射,EXPOSE)
    • host: 不会获得独立的network namespace,而是会使用宿主机的IP和端口
    • none: 属于无网络, 不能与外界网络通信
    • network
  3. 示例:

     # 端口映射到主机指定端口
     $ docker run -d -p 8080:80 nginx
     19ab6bbe0145d179d35bec232e6aaf643613abbaec96ba58e8ff7e11546a7170
    
     $ docker ps
     CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                           NAMES
     19ab6bbe0145        nginx               "nginx -g 'daemon off"   15 seconds ago      Up 14 seconds       443/tcp, 0.0.0.0:8080->80/tcp   hopeful_minsky
    
     $ netstat -na | grep 8080
     tcp6       0      0  ::1.8080               *.*                    LISTEN
     tcp4       0      0  *.8080                 *.*                    LISTEN
    
     $ curl http://localhost:8080
    
     # 端口映射到主机任意一个端口
     $ docker run -d -P nginx
     30e8063166177f4884f183a3d6a6c56cb271bfa60a71436cca3a00e295692579
    
     $ docker ps
     CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                                           NAMES
     30e806316617        nginx               "nginx -g 'daemon off"   3 seconds ago       Up 2 seconds        0.0.0.0:32769->80/tcp, 0.0.0.0:32768->443/tcp   ecstatic_kalam
    
     $ netstat -na | grep 32769
     tcp6       0      0  ::1.32769              *.*                    LISTEN
     tcp4       0      0  *.32769                *.*                    LISTEN
    
     $ curl http://localhost:32769
    
  4. 注:容器的IP地址可能会随着容器的重启而改变,使用-link以指定的代号访问容器,避免容器IP地址变化导致的问题

     docker run --link=[container]:[alias] ...         # 以指定的代号访问容器,指定后容器启动时Docker会自动重新配置映射关系
    
     # eg:
     $ docker run -it --name cct2 --link cct1:webtest cj/centos
     $ ping webtest
     $ env
     $ cat /etc/hosts
    

搭建本地常用服务

MySQL

Refer 官网 | GitHub30/docs:mysql

  1. 搜索拉取image

     docker search mysql
     docker pull mysql
    
  2. build-mysql.sh (将启动一个mySQL服务容器的操作写入一个脚本,方便下次调用)

     #!/bin/sh
    
     #set vroot = /c/Users/jinc/mydocker/
     set vroot = ~/soft/mydocker
     set mysqlRoot = $vroot/mysql
    
     mkdir -p $mysqlRoot $mysqlRoot/conf $mysqlRoot/data
    
     # set config file:
     echo "[mysqld]
     character-set-server=utf8
     default_authentication_plugin=mysql_native_password
    
     [mysql]
     default-character-set=utf8
    
     [client]
     default-character-set=utf8
     " > $mysqlRoot/conf/my.cnf
    
     # start a mysql server container(name: micro-mysql)
     docker run -p 53306:3306 --name micro-mysql -v $mysqlRoot/conf:/etc/mysql/conf.d -v $mysqlRoot/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 -d mysql:latest
    
     # check result:
     docker ps
     docker logs micro-mysql
    
  3. 进入mysql server container

     $ docker exec -it micro-mysql /bin/bash
    
     # 1. check mysql version
     root@2c654afcf4a3:/# mysql -V
     mysql  Ver 8.0.11 for Linux on x86_64 (MySQL Community Server - GPL)
    
     # 2. check mysql使用my.cnf的优先级顺序
     root@2c654afcf4a3:/# mysql --verbose --help | grep my.cnf
                           order of preference, my.cnf, $MYSQL_TCP_PORT,
     /etc/my.cnf /etc/mysql/my.cnf ~/.my.cnf
    
     # 3. check configure file:
     root@2c654afcf4a3:/# cat /etc/mysql/conf.d
     [mysqld]
     character-set-server=utf8
     default_authentication_plugin=mysql_native_password
    
     [mysql]
     default-character-set=utf8
    
     [client]
     default-character-set=utf8
    
     # 4. 连接mysql
     root@2c654afcf4a3:/# mysql -u root -p                                               
     Enter password:
     Welcome to the MySQL monitor.  Commands end with ; or \g.
     Your MySQL connection id is 8
     Server version: 8.0.11 MySQL Community Server - GPL
    
     Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
    
     Oracle is a registered trademark of Oracle Corporation and/or its
     affiliates. Other names may be trademarks of their respective
     owners.
    
     Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
    
     mysql> show databases;
     +--------------------+
     | Database           |
     +--------------------+
     | information_schema |
     | mysql              |
     | performance_schema |
     | sys                |
     +--------------------+
     4 rows in set (0.01 sec)
    
     mysql> 
    
     # 5. 修改root密码
     mysql> ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY '123456';
     mysql> flush privileges;
     mysql> select * from mysql.tables_priv;
    
  4. 检查mysql server绑定到宿主机上的进程:

     # linux
     netstat -nultp
    
     # windows
     netstat -ano | findstr 53306
     tasklist | findstr 2636
    
     # mac
     lsof -i tcp:53306
    
  5. 在外部连接mysql server,使用客户端工具

     $ mysql -h 127.0.0.1 -P 53306 -u root -p
    
     # 创建新用户
     mysql> SELECT User, Host FROM mysql.user;
     mysql> create user 'cj'@'%' identified by '123';  
     mysql> flush privileges;  
    
     # 创建数据库,并设置权限
     mysql> create database golf;
     mysql> grant all on golf.* to cj@'%' Identified by '123';
     mysql> flush privileges;  
    
     # 检查权限
     mysql> select * from mysql.tables_priv;
     mysql> exit
    
     # 使用新创建的用户连接
     $ mysql -u cj -p
    
  6. 管理mysql server container:

     # check container
     docker ps
     docker ps -a -f "name=micro-mysql"
    
     # start/stop container:
     docker stop micro-mysql
     docker start micro-mysql
    
     # stop/remove container:
     docker stop micro-mysql
     docker rm micro-mysql
    
     # re-enter container:
     docker exec -it micro-mysql /bin/bash
     # connect mysql on mysql container
     mysql -u root -p
    

Issues:

  1. mysqld: [Warning] World-writable config file /etc/mysql/conf.d/my.cnf is ignored.
    • 权限全局可写,任何一个用户都可以写,mysql担心这种文件被其他用户恶意修改,所以忽略掉这个配置文件。导致无法进入,这也是mysql的安全机制之一
    • 修改该文件的权限(chmod 644 /etc/mysql/conf.d/my.cnf)也会失败
    • This is a know boot2docker issues
  2. Unable to load authentication plugin caching_sha2_password.
    • Refer: 安装 mysql 8.0后;root用户在客户端连接不上 | Authentication plugin 'caching_sha2_password' cannot be loaded
    • 修正方式一:第一次启动mysql容器时执行mysqld --default-authentication-plugin=mysql_native_password
        cd /c/Users/jinc/mydocker/
        docker run -p 53306:3306 --name micro-mysql -v `pwd`/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 -d mysql:latest mysqld --default-authentication-plugin=mysql_native_password
      
    • 修正方式二:使用配置文件my.cnf default_authentication_plugin=mysql_native_password
    • 检查修正是否成功:
        mysql> select user, host, plugin, authentication_string from mysql.user;
        +------------------+-----------+-----------------------+-------------------------------------------+
        | user             | host      | plugin                | authentication_string                     |
        +------------------+-----------+-----------------------+-------------------------------------------+
        | root             | %         | mysql_native_password | *6BB4837EB74329105EE4568DDA7DC67ED2CA2AD9 |
        | mysql.infoschema | localhost | mysql_native_password | *THISISNOTAVALIDPASSWORDTHATCANBEUSEDHERE |
        | mysql.session    | localhost | mysql_native_password | *THISISNOTAVALIDPASSWORDTHATCANBEUSEDHERE |
        | mysql.sys        | localhost | mysql_native_password | *THISISNOTAVALIDPASSWORDTHATCANBEUSEDHERE |
        | root             | localhost | mysql_native_password | *6BB4837EB74329105EE4568DDA7DC67ED2CA2AD9 |
        +------------------+-----------+-----------------------+-------------------------------------------+
        5 rows in set (0.00 sec)
      

MongoDB

Refer 官网 | Mongodb账户管理

  1. 搜索拉取image

     docker search mongo
     docker pull mongo
    
  2. build-mongo.sh ( mongod container)

     #!/bin/bash
    
     cd ~/soft/mydocker
     mkdir -p mongo/data mongo/data/db mongo/data/configdb mongo/backup
     cd mongo
    
     # MONGO_INITDB_ROOT_USERNAME & MONGO_INITDB_ROOT_PASSWORD create a new user for authentication database: admin,give role: root
     # then the mongodb will start with authentication enabled : mongod --auth
     docker run --name micro-mongo -p 27017:27017 -v `pwd`/data/db:/data/db -v `pwd`/data/configdb:/data/configdb -v `pwd`/backup:/backup -e MONGO_INITDB_ROOT_USERNAME=cj -e MONGO_INITDB_ROOT_PASSWORD=123456 -d mongo:latest
    
     docker ps
     docker logs micro-mongo
    
     # docker exec -it micro-mongo /bin/bash
     # mongo --nodb
     # quit()
     # mongo -u cj -p 123456 --authenticationDatabase admin
    
  3. 进入mongo server container

     $ docker exec -it micro-mongo /bin/bash
    
     root@6e5dc21a43a7:/# mongo --nodb
     MongoDB shell version v4.0.1
     Welcome to the MongoDB shell.
     For interactive help, type "help".
     For more comprehensive documentation, see
     http://docs.mongodb.org/
     Questions? Try the support group
     http://groups.google.com/group/mongodb-user
     > quit()
    
     root@6e5dc21a43a7:/# mongo -u cj -p 123456 --authenticationDatabase admin
     MongoDB shell version v4.0.1
     connecting to: mongodb://127.0.0.1:27017
     MongoDB server version: 4.0.1
     ---
     Enable MongoDB free cloud-based monitoring service, which will then receive and display
     metrics about your deployment (disk utilization, CPU, operation statistics, etc).
    
     The monitoring data will be available on a MongoDB website with a unique URL accessible to you
     and anyone you share the URL with. MongoDB may use this information to make product
     improvements and to suggest MongoDB products and deployment options to you.
    
     To enable free monitoring, run the following command: db.enableFreeMonitoring()
     To permanently disable this reminder, run the following command: db.disableFreeMonitoring()
     ---
     > show dbs
     admin   0.000GB
     config  0.000GB
     local   0.000GB
     > use admin
     switched to db admin
     > use demo
     switched to db demo
     > db
     demo
     > show dbs
     admin   0.000GB
     config  0.000GB
     local   0.000GB
     > db.articles.insert({title:"MongoDB Aggregation"},{w:1})
     WriteResult({ "nInserted" : 1 })
     > db.articles.find().pretty()
     {
             "_id" : ObjectId("5b87af7d680f82a036444a66"),
             "title" : "MongoDB Aggregation"
     }
     > show dbs
     admin   0.000GB
     config  0.000GB
     demo    0.000GB
     local   0.000GB
     > exit
     bye
     root@480e8bf33600:/#
    
  4. 检查绑定到宿主机上的进程:

     # linux
     netstat -nultp
    
     # windows
     netstat -ano | findstr 27017
     tasklist | findstr 2636
    
     # mac
     lsof -i tcp:27017
    
  5. 在外部连接mongoDB

    • 使用客户端工具: MongoDB Compass
    • 创建启动一个mongo container作为客户端,mongoCli.sh:

      #!/bin/bash
      
      # admin: authentication database; some-db: the dabatase after login; if not set,use default db:test
      docker run -it --rm --link micro-mongo:mongod --name mongo-client mongo:latest mongo -host mongod -u cj -p 123456 --authenticationDatabase admin demo
      
  6. 管理 container:

     # check container
     docker ps
     docker ps -a -f "name=micro-mongo"
    
     # start/stop container (mongo server:mongod):
     docker stop micro-mongo
     docker start micro-mongo
    
     # stop/remove container:
     docker stop micro-mongo
     docker rm micro-mongo
    
     # re-enter container:
     docker exec -it micro-mongo /bin/bash
     # connect mongo server on mongo container
     mongo -u cj -p 123456 --authenticationDatabase admin
     # close mongodb server:
     ps
     kill -2 pid     # 不要kill -9 pid 方式关闭mongodb的进程,这样会有很多服务资源没法回收,或使用db.shutdownServer()
    

Issues:

docker-machine restart lost data issue

  • 解决方案:建一个单独的数据卷(-v)为其他容器提供数据,再使用--volumes-from挂载该数据卷

      # /home/docker/mongo is container path
      # docker create -v /home/docker/mongo --name mongo-store mongo
    
      # 创建数据卷容器,docker-machine重启,micro-mongo container删除不会导致数据丢失
      docker create --name store-mongo mongo 
      docker run --volumes-from store-mongo --name micro-mongo -p 27017:27017 -e MONGO_INITDB_ROOT_USERNAME=mongoadmin -e MONGO_INITDB_ROOT_PASSWORD=123456 -d mongo:latest
    
  • 完整演示和验证:

    1. 建一个单独的数据卷

       # 这里会自动为container的/data/configdb,/data/db建立Mount
       docker@default:~$ docker create --name store-mongo mongo
       eb254174f17adb11216df5db4a5cb9041ce21ad0de232e16f9b7c7263ba4e136
      
       docker@default:~$ docker volume ls
       DRIVER              VOLUME NAME
       local               9bbb8de44a1d9e56bfec77086b71c15eee6eea01c5080a7116cc6294650a9912
       local               d2620205c1bf49621808e0d562615d3bf06776a96f05786398ccfd1c8686bf7b
      
       docker@default:~$ docker inspect --format="{{.Mounts}}" store-mongo
       [{volume 9bbb8de44a1d9e56bfec77086b71c15eee6eea01c5080a7116cc6294650a9912 /mnt/sda1/var/lib/docker/volumes/9bbb8de44a1d9e56bfec77086b71c15eee6eea01c5080a7116cc6294650a9912/_data /data/configdb local  true } {volume d2620205c1bf49621808e0d562615d3bf06776a96f05786398ccfd1c8686bf7b /mnt/sda1/var/lib/docker/volumes/d2620205c1bf49621808e0d562615d3bf06776a96f05786398ccfd1c8686bf7b/_data /data/db local  true }]
      
    2. 创建启动一个container as mongo server : micro-mongo,并挂载数据卷store-mongo

       docker@default:~$ docker run --volumes-from store-mongo --name micro-mongo -p 27017:27017 -e MONGO_INITDB_ROOT_USERNAME=mongoadmin -e MONGO_INITDB_ROOT_PASSWORD=123456 -d mongo:latest
       480e8bf33600e156403293e44172a329dd9c2f023421446ab80b4e311e3bef11
      
       docker@default:~$ docker ps
       CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                      NAMES
       480e8bf33600        mongo:latest        "docker-entrypoint..."   3 seconds ago       Up 2 seconds        0.0.0.0:27017->27017/tcp   micro-mongo
      
    3. 进入刚才创建的mongo server container:micro-mongo

       docker@default:~$ docker exec -it micro-mongo /bin/bash
       root@480e8bf33600:/# ps
         PID TTY          TIME CMD
          96 ?        00:00:00 bash
         105 ?        00:00:00 ps
       root@480e8bf33600:/# mongo -u mongoadmin -p 123456 --authenticationDatabase admin
       > show dbs
       admin   0.000GB
       config  0.000GB
       demo    0.000GB
       local   0.000GB
       > exit
       bye
       root@480e8bf33600:/# exit
       exit
       docker@default:~$
      
    4. 创建启动一个container as mongo client : micro-client

       docker@default:~$ docker run -it --rm --link micro-mongo:mongod --name mongo-client mongo:latest mongo -host mongod -u mongoadmin -p 123456 --authenticationDatabase admin demo
       > show dbs
       admin   0.000GB
       config  0.000GB
       demo    0.000GB
       local   0.000GB
       > exit
      
    5. 删除mongo server container & volume:

       docker@default:~$ docker stop micro-mongo
       micro-mongo
       docker@default:~$ docker rm -v micro-mongo
       micro-mongo
      
       # 删除容器后volume仍然存在
       docker@default:~$ docker volume ls
       DRIVER              VOLUME NAME
       local               9bbb8de44a1d9e56bfec77086b71c15eee6eea01c5080a7116cc6294650a9912
       local               d2620205c1bf49621808e0d562615d3bf06776a96f05786398ccfd1c8686bf7b
      
       docker@default:~$ docker rm -v store-mongo
       store-mongo
       docker@default:~$ docker volume ls
       DRIVER              VOLUME NAME
       docker@default:~$
      

Redis

Refer 官网

  1. run redis conainer: micro-redis
     # docker run -idt -p 6379:6379 -v `pwd`/data:/data -v `pwd`/conf/redis.conf:/etc/redis/redis.conf --name micro-redis redis:latest
     docker run -idt -p 6379:6379 -v `pwd`/data:/data -v `pwd`/conf:/etc/redis --name micro-redis redis:latest redis-server /etc/redis/redis.conf
    
    • Note: update redis.conf
        daemonize no
        #bind 127.0.0.1
        requirepass 123456
      
  2. re-enter redis container
     docker exec -it micro-redis /bin/bash
     root@5c82ac6a4f8a:/etc/redis# redis-server -v
     Redis server v=4.0.10 sha=00000000:0 malloc=jemalloc-4.0.3 bits=64 build=3e68f04515f466a2
     root@5c82ac6a4f8a:/etc/redis# redis-cli -v
     redis-cli 4.0.10
    
  3. run redis-cli container:
     # -h host, -p port -a authPwd
     # docker run -it --rm --link micro-redis:redis --name redis-client redis:latest redis-cli -h redis -p 6379 -a 123456
     docker run -it --rm --link micro-redis:redis --name redis-client redis:latest redis-cli -h redis -p 6379
     > auth 123456
     > keys *
     > set name Tom
     > get name
    
  4. Redis GUI Tool: Redis Desktop Manager(RDM)
    • Github
    • Document
    • mac:
        brew cask install rdm
        brew cask install Caskroom/cask/rdm
      

Zookeeper

Refer 官网

  1. run zookeeper container: micro-zoo

     cd ~/zookeeper
     mkdir -p zk01/conf zk01/data zk01/datalog
    
     docker run --name micro-zoo -p 2181:2181 -v `pwd`/zk01/conf:/conf -v `pwd`/zk01/data:/data -v `pwd`/zk01/datalog:/datalog -d zookeeper:latest
    
     # Since the Zookeeper "fails fast" it's better to always restart it
     # docker run --name micro-zoo -p 2181:2181 -v `pwd`/zk01/conf:/conf -v `pwd`/zk01/data:/data -v `pwd`/zk01/datalog:/datalog --restart always -d zookeeper:latest
    
    • Note: conf/zoo.cfg
        clientPort=2181
        dataDir=/data
        dataLogDir=/datalog
        tickTime=2000
        initLimit=5
        syncLimit=2
        maxClientCnxns=60
      
  2. re-enter zookeeper container

     $ docker exec -it micro-zoo /bin/bash
    
     bash-4.4# ls bin
     README.txt    zkCli.cmd     zkEnv.cmd     zkServer.cmd
     zkCleanup.sh  zkCli.sh      zkEnv.sh      zkServer.sh
    
     # ZK Server
     bash-4.4# zkServer.sh start/stop/status/restart
    
     #ZK Client
     bash-4.4# zkCli.sh -server 127.0.0.1:2181
    
  3. run ZkClient Container:

     # Connect to Zookeeper from the Zookeeper command line client:
     $ docker run -it --rm --link micro-zoo:zk01 --name zoo-client zookeeper:latest zkCli.sh -server zk01:2181
     [zk: zk01:2181(CONNECTED) 1] ls /
     [zk: zk01:2181(CONNECTED) 1] create /zk testData
     [zk: zk01:2181(CONNECTED) 1] get /zk
     [zk: zk01:2181(CONNECTED) 1] set /zk testData2
     [zk: zk01:2181(CONNECTED) 1] get /zk
     [zk: zk01:2181(CONNECTED) 1] stat /zk
     [zk: zk01:2181(CONNECTED) 1] quite
    
  4. GUI Tool: zkui

Reference

ruanyf/Docker 入门教程 ruanyf/Docker 微服务教程 Docker 入门 每天5分钟玩转Docker容器技术