• Docker安装和基本配置


    简介

    全部操作来自于英文官方文档(两三年前的)。官网地址:https://docs.docker.com/get-started/

    docker的优点:
    灵活的 Flexible: Even the most complex applications can be containerized.
    轻量级 Lightweight: Containers leverage and share the host kernel.
    可交互 Interchangeable: You can deploy updates and upgrades on-the-fly.
    可移植 Portable: You can build locally, deploy to the cloud, and run anywhere.
    可伸缩 Scalable: You can increase and automatically distribute container replicas.
    可叠加 Stackable: You can stack services vertically and on-the-fly.

    镜像和容器

    通过运行镜像image来启动容器。镜像是一个可执行的包,它包含了运行应用程序所需的一切——代码、运行时、库、环境变量和配置文件。
    容器是镜像的运行实例,你可以是使用命令docker ps来查看运行情况,就跟在Linux当中一样。
    举例来说,就相当于镜像是一个类,容器是镜像的一个实例。

    容器和虚拟机

    一个容器和主机共享内核,属于轻量级。
    相比之下,虚拟机试试建立了一个Guest账户,需要的资源比应用程序所需的多。

    版本介绍

    Docker两个版本:免费社区版(CE)和收费企业版(EE)。
    Docker社区版(CE)有两个更新的渠道,stable和edge:
    稳定版stable每季度提供更新
    边缘版edge每月提供更新
    后续所有的介绍,全部基于社区版。和企业版不同之处见下图:

    (img-ubJfKVJ0-1661998976988)(images/screenshot_1661998048891.png)]

    安装流程

    Docker所有版本的安装步骤可以参看官网,本篇只介绍Docker CE 在Windows10 、 Ubuntu16.04 、 Mac 下的安装。 官网地址:https://docs.docker.com/install/

    Windows下的安装

    和其他绝大部分软件一样,只需要下载安装包,然后运行完成安装步骤即可。安装包下载地址可以从官网中找到,也可以直接访问https://docs.docker.com/docker-for-windows/install/, 链接中提供的基本的效果。

    Mac下的安装

    和Windows基本一致,先下载安装包,然后拖拽完成整个步骤。下载地址:https://docs.docker.com/docker-for-mac/install/#download-docker-for-mac
    安装完成后,为了加快后续操作加载速度,可以修改下registry mirrors为http://hub-mirror.c.163.com
    在这里插入图片描述

    Ubuntu下的安装

    测试服务器我用了腾讯云的。系统参数如下
    在这里插入图片描述

    如果电脑已经安装了旧版本的Docker,可以先进行卸载

    sudo apt-get remove docker docker-engine docker.io
    
    • 1

    依次执行以下命令

    # 更新apt
    sudo apt-get update
    # 允许apt访问https
    sudo apt-get install \
        apt-transport-https \
        ca-certificates \
        curl \
        software-properties-common
    # 添加Docker的official GPG key:
    curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
    # 检查
    sudo apt-key fingerprint 0EBFCD88
    # 这个是检查的打印结果,不用输入
    pub   4096R/0EBFCD88 2017-02-22
          Key fingerprint = 9DC8 5822 9FC7 DD38 854A  E2D8 8D81 803C 0EBF CD88
    uid                  Docker Release (CE deb) 
    sub   4096R/F273FCD8 2017-02-22
    # 安装stable repository,这个是必须的
    sudo add-apt-repository \
       "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
       $(lsb_release -cs) \
       stable"
    # 开始安装
    sudo apt-get update
    sudo apt-get install docker-ce
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    以上命令安装的是最新版本,如果是生产环境,可能会固定某个版本,通过以下命令查看支持的版本

    apt-cache madison docker-ce
    
    • 1

    有了版本号,就可以安装指定的版本了

    $ sudo apt-get install docker-ce=18.03.0~ce-0~ubuntu
    
    • 1

    安装完成后,查看版本

    $ docker --version
    Docker version 18.03.0-ce, build 0520e24
    
    • 1
    • 2

    详细信息

    # 下面两个命令是等价的,用哪个都可以
    $ docker version
    $ docker info
    
    • 1
    • 2
    • 3

    安装样例(docker镜像,这里先运行就可以,后续章节会有介绍)

    $ docker run hello-world
    
    • 1

    查看已安装样例

    $ docker image ls
    $ docker container ls --all
    
    • 1
    • 2

    备忘记录

    # 查看Docker支持的所有命令
    docker
    docker container --help
    
    # 查看Docker的版本信息和详细信息
    docker --version
    docker version
    docker info
    
    # 运行Docker的镜像
    docker run hello-world
    
    # 查看Docker中运行的镜像
    docker image ls
    
    # 查看Docker中所有镜像,包括停止的等等
    docker container ls
    docker container ls --all
    docker container ls -aq
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    部署第一步:容器和镜像

    一个项目的部署问题。线上环境安装的JDK版本是1.6,而最新开发完成的项目需要的JDK版本最低是1.8,在1.6的条件下不能正常启动。但是,如果把线上的1.6升级到1.8,旧系统运行又会出现问题。
    如果使用了Docker,那么就完全没有这方面的担忧了。Docker是直接运行镜像(image)的,跟服务器的环境无关,需要的运行环境都在镜像当中。如果要自己写个镜像,那么简单说就是需要一个名称是Dockerfile的文件(没有任何后缀,文件名称就是Dockerfile)来定义。
    后续的例子都是来自官网,可以去看英文原版:https://docs.docker.com/get-started/part2/#recap-and-cheat-sheet-optional

    Dockerfile

    这篇主要介绍什么是容器和镜像,涉及到具体语言和业务的,可以暂时不用深究,明白是要干什么的就行。操作环境使用的Ubuntu16.04。
    在空白目录下新建名称是Dockerfile的文件

    # 目录随意,是空的就行
    sudo mkdir /usr/local/test
    cd /usr/local/test
    sudo vim Dockerfile
    
    • 1
    • 2
    • 3
    • 4

    文件内容是

    # 从远程拉取python需要的运行环境
    FROM python:2.7-slim
    # 设置工作目录
    WORKDIR /app
    # 复制当前目录内容到上面设置好的工作目录
    ADD . /app
    # 安装requirements.txt文件中指定的软件
    RUN pip install --trusted-host pypi.python.org -r requirements.txt
    # 容器端口使用80(不是硬件设备的端口)
    EXPOSE 80
    # 定义环境变量
    ENV NAME World
    # 容器启动时运行app.py文件
    CMD ["python", "app.py"]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    Dockerfile中使用了两个文件,requirements.txt和app.py,在相同目录下新建这两个文件。
    requirements.txt的内容

    Flask
    Redis
    
    • 1
    • 2

    app.py的内容

    from flask import Flask
    from redis import Redis, RedisError
    import os
    import socket
    
    # Connect to Redis
    redis = Redis(host="redis", db=0, socket_connect_timeout=2, socket_timeout=2)
    
    app = Flask(__name__)
    
    @app.route("/")
    def hello():
        try:
            visits = redis.incr("counter")
        except RedisError:
            visits = "cannot connect to Redis, counter disabled"
    
        html = "

    Hello {name}!

    " \ "Hostname: {hostname}
    " \ "Visits: {visits}" return html.format(name=os.getenv("NAME", "world"), hostname=socket.gethostname(), visits=visits) if __name__ == "__main__": app.run(host='0.0.0.0', port=80)
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    以上的含义是完成Flask和Redis的安装,然后打印部分内容,因为Redis没有运行,会打印失败信息。

    编译和运行

    先确保cd进入了上面文件所在的文件夹,使用下面的命令开始编译,其中friendlyhello是自己定义的名称,最后面有个点(表示当前目录)

    sudo docker build -t friendlyhello .
    
    • 1

    正常情况下,打印的内容为

    Sending build context to Docker daemon  4.608kB
    Step 1/7 : FROM python:2.7-slim
    ...(好多内容,忽略不写了)
    Step 7/7 : CMD ["python", "app.py"]
     ---> Running in e710f92c9af1
    Removing intermediate container e710f92c9af1
     ---> d68b0dcd2d36
    Successfully built d68b0dcd2d36
    Successfully tagged friendlyhello:latest
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    上面步骤完成后,就生成镜像了,查看下所有镜像的列表:

    $ sudo docker image ls
    
    • 1

    生成镜像之后自然是运行,执行下面语句:

    docker run -p 4000:80 friendlyhello
    
    • 1

    其中,4000:80的含义是使用计算机真实的4000端口和镜像中的80端口匹配(还记得Dockerfile中定义了一个80吗,不是服务器的,这里可以映射关系),要访问docker中的80端口,只需要访问计算机的4000端口即可。
    此时计算机是卡住的状态,要想检查是不是正常,可以使用浏览器查看http://ip地址:4000
    自然,我们是不希望窗口一直卡住不能动的(如果要停止, ctrl+c 就行了),能不能后台运行,不影响其他操作呢?只需要加上一个-d,就像其他linux命令一样

    docker run -d -p 4000:80 friendlyhello
    
    • 1

    此时除了用浏览器查看,也可以使用curl命令,就像这样

    curl http://localhost:4000
    
    • 1

    如果运行其实端口被占用,可以参照左侧目录附录一

    共享镜像

    上面的操作已经可以完成了本地的运行,但是docker还为我们提供了更方便的地方,比如我用mac运行成功了,现在要放到ubuntu服务器上,所有操作都再运行一次是很不方便的,假如我们把运行成功的镜像上传到一个地方,其他计算机要使用的时候,直接拉取这个镜像,岂不是更方便。那么我们就先登录可以放置我们镜像的网站:http://cloud.docker.com
    如果没有账号,需要先注册,注册时候验证码会因为网络环境刷新比较吃力,可以换换网络或者找个梯子。我已经注册成功,用户名是fymod。

    sudo docker login
    Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.
    Username: fymod
    Password: 
    Login Succeeded
    
    • 1
    • 2
    • 3
    • 4
    • 5

    给镜像打个标记username/repository:tag,其中tag是可选的,但是强烈建议加上。

    sudo docker tag friendlyhello fymod/get-started:part2
    
    • 1

    查看下当前运行的镜像是否多出来了fymod/get-started,这个镜像是可以推送到云端的。

    sudo docker image ls
    
    • 1

    把本地镜像推送到云端

    $ sudo docker push fymod/get-started:part2
    
    • 1

    推送完成后,使用注册下来的账号登录https://hub.docker.com/查看,如果有了,其他电脑就可以直接使用。
    我们换台只安装了docker的计算机运行下面的命令:

    $ sudo docker run -p 4000:80 fymod/get-started:part2
    
    • 1

    如果本地有这个镜像,就直接使用本地的,如果没有,就从云端拉取,和之前本地运行的命令很相似,只是将之前的friendhello换成了定义的tag。

    备忘记录

    # 使用Dockerfile建立一个镜像
    docker build -t friendlyhello . 
    # 前端运行镜像
    docker run -p 4000:80 friendlyhello 
    # 后台运行镜像
    docker run -d -p 4000:80 friendlyhello 
    # 列出所有运行中的容器
    docker container ls 
    # 列出全部容器,即便没有运行
    docker container ls -a 
    # 停止特定的容器
    docker container stop 
    # 强制停止指定的容器
    docker container kill 
    # 移除指定的容器
    docker container rm 
    # 移除全部容器
    docker container rm $(docker container ls -a -q)  
    # 查看全部镜像列表
    docker image ls -a  
    # 移除指定镜像
    docker image rm  
    # 移除全部镜像
    docker image rm $(docker image ls -a -q)  
    # 登录云端
    docker login   
    # 给要上传云端的镜像打标记
    docker tag  username/repository:tag 
    # 指定标记的镜像上传到云端
    docker push username/repository:tag     
    # 运行指定标记的镜像
    docker run username/repository:tag  
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    部署第二步:服务和集群

    先声明服务和堆栈的概念。上一节介绍了镜像是容器的实例,而服务可以运行很多个容器。比如本篇要讲前一节介绍的demo做成5个容器实例来访问。其实很简单,编写一个yaml格式的文件就行了。本篇对应两篇官方英文网址为:
    https://docs.docker.com/get-started/part3/
    https://docs.docker.com/get-started/part4/

    docker-compose.yml

    文件位置没有要求,放到哪里都行。

    version: "3"
    services:
      web:
        image: fymod/get-started:part2
        deploy:
          replicas: 5
          resources:
            limits:
              cpus: "0.1"
              memory: 50M
          restart_policy:
            condition: on-failure
        ports:
          - "80:80"
        networks:
          - webnet
    networks:
      webnet:
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    各个字段含义如下
    image:换成自己的镜像
    replicas:运行5个容器实例
    limits:最大10%的cpu占用和最大50M的RAM占用。
    restart_policy:失败之后立即重启
    ports:映射外部端口和docker端口
    networks:定义了一个默认的网络(支持负载均衡),可查看附录三

    运行

    sudo docker swarm init
    sudo docker stack deploy -c docker-compose.yml getstartedlab
    
    • 1
    • 2

    根据docker-compose.yml中的定义,我们的一个服务栈运行5个容器实例,先验证下

    sudo docker service ls
    sudo docker service ps getstartedlab_web
    # 如果想查看系统中全部的容器,可以运行
    sudo docker container ls -q
    
    • 1
    • 2
    • 3
    • 4

    验证

    访问http://ip地址,显示的hostname每请求5次一个循环,值就是sudo docker container ls -q当中的数据。

    重启部署

    如果要把5个实例换成10个,只需要修改docker-compose.yml中的一个数字即可,然后重启。重启的命令和启动的是一模一样,不需要自己先停止再去启动

    sudo docker stack deploy -c docker-compose.yml getstartedlab
    
    • 1

    停止应用和集群

    停止应用

    $ sudo docker stack rm getstartedlab
    
    • 1

    停止集群

    $ sudo docker swarm leave --force
    
    • 1

    集群效果

    前面已经实现了一台计算机上运行很多容器实例,本部分介绍多台计算机的集群效果。docker集群由管理员和worker组成,本篇使用一台机器作为管理员(就是一直用的这台),另一台(一个安装了docker的新计算机)作为worker。
    英文官网上这部分是用的虚拟机,因为我的ubuntu服务器不支持虚拟化,就用了两台物理机。如果要熟悉虚拟机相关注意事项和基本命令,可以先查看左侧附录二。

    在一台服务器上执行命令,设置为管理员。

    docker swarm init --advertise-addr 10.72.72.98
    
    • 1

    其中,10.72.72.98是计算机ip地址,替换为自己真实的即可
    打印结果如下

    Swarm initialized: current node (fszwnygfkgk0tdzlwlc1tuxf3) is now a manager.
    
    To add a worker to this swarm, run the following command:
    
        docker swarm join --token SWMTKN-1-5subd4cg5rjb6hs54b2ctxmihyxgfp32d81suuqqmiks1kawar-44u7f7vlhxydaj8dad35ff4x3 10.72.72.98:2377
    
    To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    中间一行命令表示如果要把机器加入到这个集群成为worker,直接把这句复制过去运行。所以在第二台安装了docker的计算机上来直接运行:

    docker swarm join --token SWMTKN-1-5subd4cg5rjb6hs54b2ctxmihyxgfp32d81suuqqmiks1kawar-44u7f7vlhxydaj8dad35ff4x3 10.72.72.98:2377
    
    • 1

    运行完成后可以来查看

    sudo docker node ls
    
    • 1

    命令和之前的也一样:

    sudo docker swarm init
    sudo docker stack deploy -c docker-compose.yml getstartedlab
    
    • 1
    • 2

    查看结果

    sudo docker service ls
    docker stack ps getstartedlab
    
    • 1
    • 2

    访问两台计算机的80端口,看看是不是都有结果,也可以使用curl

    curl 管理员计算机ip地址
    curl worker计算机ip地址
    
    • 1
    • 2

    备忘记录

    其他命令可以查看附录二,docker-machine括号里面的都是真机可用的。

    # 堆栈和应用列表
    docker stack ls    
    # 运行指定的组成文件
    docker stack deploy -c   
    # 列出运行的服务列表
    docker service ls  
    # 列出与应用程序相关联的任务
    docker service ps   
    # 检查任务或者容器
    docker inspect   
    # 列出所有容器的id
    docker container ls -q   
    # 移除应用
    docker stack rm       
    # 从管理员移除单一节点
    docker swarm leave --force
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    部署第三步:可视化

    回头看下之前的docker-compose.yml,里面只有一个主节点web,用来运行我们demo当中的服务。其实这里面可以添加很多的节点,并非只能添加一个,比如前面例子一直没有实现的redis节点,同时也可以添加docker镜像已经有的可视化节点。这部分英文官方文档地址是:https://docs.docker.com/get-started/part5/

    添加节点

    修改docker-compose.yml文件,添加两个节点,分别实现可视化和redis管理。

    version: "3"
    services:
      web:
        image: fymod/get-started:part2
        deploy:
          replicas: 5
          restart_policy:
            condition: on-failure
          resources:
            limits:
              cpus: "0.1"
              memory: 50M
        ports:
          - "80:80"
        networks:
          - webnet
      visualizer:
        image: dockersamples/visualizer:stable
        ports:
          - "8080:8080"
        volumes:
          - "/var/run/docker.sock:/var/run/docker.sock"
        deploy:
          placement:
            constraints: [node.role == manager]
        networks:
          - webnet
      redis:
        image: redis
        ports:
          - "6379:6379"
        volumes:
          - "/home/docker/data:/data"
        deploy:
          placement:
            constraints: [node.role == manager]
        command: redis-server --appendonly yes
        networks:
          - webnet
    networks:
      webnet:
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    其中,visualizer节点是可视化效果,可以用网页打开查看。redis节点是数据存储用的。因为redis数据最好存储到物理机上,而不是docker中的位置,volumes选项就是将docker中的位置映射到物理机的/home/docker/data目录下。稳妥起见,新建下目录。

    sudo mkdir /home/docker/data
    sudo mkdir ./data
    
    • 1
    • 2

    然后运行

    $ sudo docker stack deploy -c docker-compose.yml getstartedlabc
    
    • 1

    查看

    sudo docker service ls
    
    • 1

    如果redis或者visualizer启动失败,可能是原因是本地没有镜像,也没有成功拉取下来,可以先手动执行下对应的步骤,然后ctrl+c停止

    sudo docker run 8080:8080 dockersamples/visualizer:stable
    sudo docker run -p 6379:6379 redis
    
    • 1
    • 2

    继续运行

    $ sudo docker stack deploy -c docker-compose.yml getstartedlabc
    
    • 1

    网页访问
    http://ip地址:8080http://ip地址查看

    附录一:端口占用

    比如ssh连接自己断开了,没有使用ctrl+c停止,那么再连接上运行命令的时候,就会提示端口被占用。停止方法:
    查看运行的镜像

    $ sudo docker container ls
    CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                  NAMES
    e559c1e88f15        friendlyhello       "python app.py"     36 seconds ago      Up 34 seconds       0.0.0.0:4000->80/tcp   sad_stallman
    
    • 1
    • 2
    • 3

    有了上面的编码,就能直接停止了,序号可以只输入一部分,比如

    $ sudo docker container stop e559c
    
    • 1

    附录二:虚拟机相关内容

    ubuntu检查cpu是否支持虚拟化

    $ sudo apt-get install cpu-checker
    $ kvm-ok
    
    • 1
    • 2

    支持的话,打印的是

    INFO: /dev/kvm exists
    KVM acceleration can be used
    
    • 1
    • 2

    不支持的话,打印的是

    INFO: Your CPU does not support KVM extensions
    INFO: For more detailed results, you should run this as root
    HINT:   sudo /usr/sbin/kvm-ok
    
    • 1
    • 2
    • 3
    安装虚拟机

    如果支持虚拟化,安装虚拟机

    sudo apt-get install libqt5x11extras5 libsdl1.2debian
    sudo apt-get install virtualbox
    
    • 1
    • 2

    当然也可以自己手动下载下来,然后安装下载下来的文件。下载地址是https://www.virtualbox.org/wiki/Linux_Downloads
    安装命令是

    $ sudo dpkg -i virtualbox-5.2_5.2.8-121009~Ubuntu~xenial_amd64.deb
    
    • 1
    安装docker-machine

    下面的命令全部复制执行即可

    curl -L https://github.com/docker/machine/releases/download/v0.13.0/docker-machine-`uname -s`-`uname -m` >/tmp/docker-machine &&
    chmod +x /tmp/docker-machine &&
    sudo cp /tmp/docker-machine /usr/local/bin/docker-machine
    
    • 1
    • 2
    • 3

    检查用

    $ sudo docker-machine version
    
    • 1

    使用 docker-machine 建立 vms

    docker-machine create --driver virtualbox myvm1
    docker-machine create --driver virtualbox myvm2
    
    • 1
    • 2

    查看

    docker-machine ls
    
    • 1

    docker-machine命令

    # 在Mac, Win7, Linux下建立虚拟机
    docker-machine create --driver virtualbox myvm1 
    # Win10下建立虚拟机
    docker-machine create -d hyperv --hyperv-virtual-switch "myswitch" myvm1 
    # 查下关于节点的基本信息
    docker-machine env myvm1     
    # 集群下节点列表
    docker-machine ssh myvm1 "docker node ls"   
    # 节点检查
    docker-machine ssh myvm1 "docker node inspect "    
    # 查看加入使用的token
    docker-machine ssh myvm1 "docker swarm join-token -q worker" 
    # 打开虚拟机的ssh连接,使用exit命令退出
    docker-machine ssh myvm1
    # 查看集群下节点列表
    docker node ls  
    # worker撤离集群
    docker-machine ssh myvm2 "docker swarm leave"  
    # 彻底关闭集群
    docker-machine ssh myvm1 "docker swarm leave -f" 
    # 虚拟机列表
    docker-machine ls 
    # 启动当前没有运行的虚拟机
    docker-machine start myvm1     
    # 查看虚拟机的环境变量
    docker-machine env myvm1      
    # mac电脑下连接到虚拟机
    eval $(docker-machine env myvm1)  
    # windows电脑下连接到虚拟机
    & "C:\Program Files\Docker\Docker\Resources\bin\docker-machine.exe" env myvm1 | Invoke-Expression 
    # 编译:管理员服务器才能使用的命令
    docker stack deploy -c  
    # 复制文件到节点主目录(ssh连接到管理员服务器)
    docker-machine scp docker-compose.yml myvm1:~ 
    # 使用ssh编译应用
    docker-machine ssh myvm1 "docker stack deploy -c  "   
    # 断开虚拟机连接
    eval $(docker-machine env -u)   
    # 停止所有运行的虚拟机
    docker-machine stop $(docker-machine ls -q)               
    # 删除所有虚拟机和他们的磁盘镜像
    docker-machine rm $(docker-machine ls -q)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    附录三:Docker的网络类型

    Docker安装后,默认会创建下面三种网络类型

    docker network ls
    NETWORK ID     NAME        DRIVER       SCOPE
    9781b1f585ae    bridge       bridge       local
    1252da701e55    host        host        local
    237ea3d5cfbf    none        null        local
    
    • 1
    • 2
    • 3
    • 4
    • 5

    启动 Docker的时候,用 --network 参数,可以指定网络类型

    docker run -itd --name test1 --network bridge --ip 172.17.0.10 centos:latest /bin/bash
    
    • 1

    bridge:桥接网络
    默认情况下启动的Docker容器,都是使用 bridge,Docker安装时创建的桥接网络,每次Docker容器重启时,会按照顺序获取对应的IP地址,这个就导致重启下,Docker的IP地址就变了

    none:无指定网络
    使用 --network=none ,docker 容器就不会分配局域网的IP

    host: 主机网络
    使用 --network=host,此时,Docker 容器的网络会附属在主机上,两者是互通的。
    例如,在容器中运行一个Web服务,监听8080端口,则主机的8080端口就会自动映射到容器中。

    创建自定义网络:(设置固定IP)
    启动Docker容器的时候,使用默认的网络是不支持指派固定IP的,如下

    # 错误命令示例
    docker run -itd --net bridge --ip 172.17.0.10 centos:latest /bin/bash
    6eb1f228cf308d1c60db30093c126acbfd0cb21d76cb448c678bab0f1a7c0df6
    docker: Error response from daemon: User specified IP address is supported on user defined networks only.
    
    • 1
    • 2
    • 3
    • 4

    步骤1: 创建自定义网络

    docker network create --subnet=172.18.0.0/16 mynetwork
    ➜ ~ docker network ls
    NETWORK ID     NAME        DRIVER       SCOPE
    9781b1f585ae    bridge       bridge       local
    1252da701e55    host        host        local
    4f11ae9c85de    mynetwork      bridge       local
    237ea3d5cfbf    none        null        local
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    步骤2: 创建Docker容器

    docker run -itd --name networkTest1 --net mynetwork --ip 172.18.0.2 centos:latest /bin/bash
    
    • 1

    附录四:文件配置

    本篇文章来自于https://www.jianshu.com/p/2217cfed29d7

    先来看一份 docker-compose.yml 文件,不用管这是干嘛的,只是有个格式方便后文解说:

    version: '2'
    services:
      web:
        image: dockercloud/hello-world
        ports:
          - 8080
        networks:
          - front-tier
          - back-tier
    
      redis:
        image: redis
        links:
          - web
        networks:
          - back-tier
    
      lb:
        image: dockercloud/haproxy
        ports:
          - 80:80
        links:
          - web
        networks:
          - front-tier
          - back-tier
        volumes:
          - /var/run/docker.sock:/var/run/docker.sock 
    
    networks:
      front-tier:
        driver: bridge
      back-tier:
    driver: bridge
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    可以看到一份标准配置文件应该包含 version、services、networks 三大部分,其中最关键的就是 services 和 networks 两个部分,下面先来看 services 的书写规则。

    1. image
    services:
      web:
        image: hello-world
    
    • 1
    • 2
    • 3

    在 services 标签下的第二级标签是 web,这个名字是用户自己自定义,它就是服务名称。
    image 则是指定服务的镜像名称或镜像 ID。如果镜像在本地不存在,Compose 将会尝试拉取这个镜像。
    例如下面这些格式都是可以的:

    image: redis
    image: ubuntu:14.04
    image: tutum/influxdb
    image: example-registry.com:4000/postgresql
    image: a4bc65fd
    
    • 1
    • 2
    • 3
    • 4
    • 5
    1. build
      服务除了可以基于指定的镜像,还可以基于一份 Dockerfile,在使用 up 启动之时执行构建任务,这个构建标签就是 build,它可以指定 Dockerfile 所在文件夹的路径。Compose 将会利用它自动构建这个镜像,然后使用这个镜像启动服务容器。
    build: /path/to/build/dir
    
    • 1

    也可以是相对路径,只要上下文确定就可以读取到 Dockerfile。

    build: ./dir
    
    • 1

    设定上下文根目录,然后以该目录为准指定 Dockerfile。

    build:
      context: ../
      dockerfile: path/of/Dockerfile
    
    • 1
    • 2
    • 3

    注意 build 都是一个目录,如果你要指定 Dockerfile 文件需要在 build 标签的子级标签中使用 dockerfile 标签指定,如上面的例子。
    如果你同时指定了 image 和 build 两个标签,那么 Compose 会构建镜像并且把镜像命名为 image 后面的那个名字。

    build: ./dir
    image: webapp:tag
    
    • 1
    • 2

    既然可以在 docker-compose.yml 中定义构建任务,那么一定少不了 arg 这个标签,就像 Dockerfile 中的 ARG 指令,它可以在构建过程中指定环境变量,但是在构建成功后取消,在 docker-compose.yml 文件中也支持这样的写法:

    build:
      context: .
      args:
        buildno: 1
        password: secret
    
    • 1
    • 2
    • 3
    • 4
    • 5

    下面这种写法也是支持的,一般来说下面的写法更适合阅读。

    build:
      context: .
      args:
        - buildno=1
        - password=secret
    
    • 1
    • 2
    • 3
    • 4
    • 5

    与 ENV 不同的是,ARG 是允许空值的。例如:

    args:
      - buildno
      - password
    
    • 1
    • 2
    • 3

    这样构建过程可以向它们赋值。

    注意:YAML 的布尔值(true, false, yes, no, on, off)必须要使用引号引起来(单引号、双引号均可),否则会当成字符串解析。

    1. command
      使用 command 可以覆盖容器启动后默认执行的命令。
    command: bundle exec thin -p 3000
    
    • 1

    也可以写成类似 Dockerfile 中的格式:

    command: [bundle, exec, thin, -p, 3000]
    
    • 1

    4.container_name
    前面说过 Compose 的容器名称格式是:
    虽然可以自定义项目名称、服务名称,但是如果你想完全控制容器的命名,可以使用这个标签指定:

    container_name: app
    
    • 1

    这样容器的名字就指定为 app 了。

    5.depends_on
    在使用 Compose 时,最大的好处就是少打启动命令,但是一般项目容器启动的顺序是有要求的,如果直接从上到下启动容器,必然会因为容器依赖问题而启动失败。
    例如在没启动数据库容器的时候启动了应用容器,这时候应用容器会因为找不到数据库而退出,为了避免这种情况我们需要加入一个标签,就是 depends_on,这个标签解决了容器的依赖、启动先后的问题。
    例如下面容器会先启动 redis 和 db 两个服务,最后才启动 web 服务:

    version: '2'
    services:
      web:
        build: .
        depends_on:
          - db
          - redis
      redis:
        image: redis
      db:
        image: postgres
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    注意的是,默认情况下使用 docker-compose up web 这样的方式启动 web 服务时,也会启动 redis 和 db 两个服务,因为在配置文件中定义了依赖关系。

    6.dns
    和 --dns 参数一样用途,格式如下:

    dns: 8.8.8.8
    
    • 1

    也可以是一个列表:

    dns:
      - 8.8.8.8
      - 9.9.9.9
    
    • 1
    • 2
    • 3

    此外 dns_search 的配置也类似:

    dns_search: example.com
    dns_search:
      - dc1.example.com
      - dc2.example.com
    
    • 1
    • 2
    • 3
    • 4
    1. tmpfs
      挂载临时目录到容器内部,与 run 的参数一样效果:
    tmpfs: /run
    tmpfs:
      - /run
      - /tmp
    
    • 1
    • 2
    • 3
    • 4
    1. entrypoint
      在 Dockerfile 中有一个指令叫做 ENTRYPOINT 指令,用于指定接入点,第四章有对比过与 CMD 的区别。
      在 docker-compose.yml 中可以定义接入点,覆盖 Dockerfile 中的定义:
    entrypoint: /code/entrypoint.sh
    
    • 1

    格式和 Docker 类似,不过还可以写成这样:

    entrypoint:
        - php
        - -d
        - zend_extension=/usr/local/lib/php/extensions/no-debug-non-zts-20100525/xdebug.so
        - -d
        - memory_limit=-1
        - vendor/bin/phpunit
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    9.env_file
    还记得前面提到的 .env 文件吧,这个文件可以设置 Compose 的变量。而在 docker-compose.yml 中可以定义一个专门存放变量的文件。
    如果通过 docker-compose -f FILE 指定了配置文件,则 env_file 中路径会使用配置文件路径。

    如果有变量名称与 environment 指令冲突,则以后者为准。格式如下:

    env_file: .env
    
    • 1

    或者根据 docker-compose.yml 设置多个:

    env_file:
      - ./common.env
      - ./apps/web.env
      - /opt/secrets.env
    
    • 1
    • 2
    • 3
    • 4

    注意的是这里所说的环境变量是对宿主机的 Compose 而言的,如果在配置文件中有 build 操作,这些变量并不会进入构建过程中,如果要在构建中使用变量还是首选前面刚讲的 arg 标签。

    1. environment
      与上面的 env_file 标签完全不同,反而和 arg 有几分类似,这个标签的作用是设置镜像变量,它可以保存变量到镜像里面,也就是说启动的容器也会包含这些变量设置,这是与 arg 最大的不同。
      一般 arg 标签的变量仅用在构建过程中。而 environment 和 Dockerfile 中的 ENV 指令一样会把变量一直保存在镜像、容器中,类似 docker run -e 的效果。
    environment:
      RACK_ENV: development
      SHOW: 'true'
      SESSION_SECRET:
    
    environment:
      - RACK_ENV=development
      - SHOW=true
      - SESSION_SECRET
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    1. expose
      这个标签与Dockerfile中的EXPOSE指令一样,用于指定暴露的端口,但是只是作为一种参考,实际上docker-compose.yml的端口映射还得ports这样的标签。
    expose:
     - "3000"
     - "8000"
    
    • 1
    • 2
    • 3
    1. external_links
      在使用Docker过程中,我们会有许多单独使用docker run启动的容器,为了使Compose能够连接这些不在docker-compose.yml中定义的容器,我们需要一个特殊的标签,就是external_links,它可以让Compose项目里面的容器连接到那些项目配置外部的容器(前提是外部容器中必须至少有一个容器是连接到与项目内的服务的同一个网络里面)。
      格式如下:
    external_links:
     - redis_1
     - project_db_1:mysql
     - project_db_1:postgresql
    
    • 1
    • 2
    • 3
    • 4
    1. extra_hosts
      添加主机名的标签,就是往/etc/hosts文件中添加一些记录,与Docker client的–add-host类似:
    extra_hosts:
     - "somehost:162.242.195.82"
     - "otherhost:50.31.209.229"
    
    • 1
    • 2
    • 3

    启动之后查看容器内部hosts:

    162.242.195.82  somehost
    50.31.209.229   otherhost
    
    • 1
    • 2
    1. labels
      向容器添加元数据,和Dockerfile的LABEL指令一个意思,格式如下:
    labels:
      com.example.description: "Accounting webapp"
      com.example.department: "Finance"
      com.example.label-with-empty-value: ""
    labels:
      - "com.example.description=Accounting webapp"
      - "com.example.department=Finance"
      - "com.example.label-with-empty-value"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    1. links
      还记得上面的depends_on吧,那个标签解决的是启动顺序问题,这个标签解决的是容器连接问题,与Docker client的–link一样效果,会连接到其它服务中的容器。
      格式如下:
    links:
     - db
     - db:database
     - redis
    
    • 1
    • 2
    • 3
    • 4

    使用的别名将会自动在服务容器中的/etc/hosts里创建。例如:

    172.12.2.186  db
    172.12.2.186  database
    172.12.2.187  redis
    
    • 1
    • 2
    • 3

    相应的环境变量也将被创建。

    1. logging
      这个标签用于配置日志服务。格式如下:
    logging:
      driver: syslog
      options:
        syslog-address: "tcp://192.168.0.42:123"
    
    • 1
    • 2
    • 3
    • 4

    默认的driver是json-file。只有json-file和journald可以通过docker-compose logs显示日志,其他方式有其他日志查看方式,但目前Compose不支持。对于可选值可以使用options指定。
    有关更多这方面的信息可以阅读官方文档:
    https://docs.docker.com/engine/admin/logging/overview/

    1. pid
    pid: "host"
    
    • 1

    将PID模式设置为主机PID模式,跟主机系统共享进程命名空间。容器使用这个标签将能够访问和操纵其他容器和宿主机的名称空间。

    1. ports
      映射端口的标签。
      使用HOST:CONTAINER格式或者只是指定容器的端口,宿主机会随机映射端口。
    ports:
     - "3000"
     - "8000:8000"
     - "49100:22"
     - "127.0.0.1:8001:8001"
    
    • 1
    • 2
    • 3
    • 4
    • 5

    注意:当使用HOST:CONTAINER格式来映射端口时,如果你使用的容器端口小于60你可能会得到错误得结果,因为YAML将会解析xx:yy这种数字格式为60进制。所以建议采用字符串格式。

    1. security_opt
      为每个容器覆盖默认的标签。简单说来就是管理全部服务的标签。比如设置全部服务的user标签值为USER。
    security_opt:
      - label:user:USER
      - label:role:ROLE
    
    • 1
    • 2
    • 3
    1. stop_signal
      设置另一个信号来停止容器。在默认情况下使用的是SIGTERM停止容器。设置另一个信号可以使用stop_signal标签。
    stop_signal: SIGUSR1
    
    • 1
    1. volumes
      挂载一个目录或者一个已存在的数据卷容器,可以直接使用 [HOST:CONTAINER] 这样的格式,或者使用 [HOST:CONTAINER:ro] 这样的格式,后者对于容器来说,数据卷是只读的,这样可以有效保护宿主机的文件系统。
      Compose的数据卷指定路径可以是相对路径,使用 . 或者 … 来指定相对目录。
      数据卷的格式可以是下面多种形式:
    volumes:
      // 只是指定一个路径,Docker 会自动在创建一个数据卷(这个路径是容器内部的)。
      - /var/lib/mysql
    
      // 使用绝对路径挂载数据卷
      - /opt/data:/var/lib/mysql
    
      // 以 Compose 配置文件为中心的相对路径作为数据卷挂载到容器。
      - ./cache:/tmp/cache
    
      // 使用用户的相对路径(~/ 表示的目录是 /home/<用户目录>/ 或者 /root/)。
      - ~/configs:/etc/configs/:ro
    
      // 已经存在的命名的数据卷。
      - datavolume:/var/lib/mysql
    如果你不使用宿主机的路径,你可以指定一个volume_driver。
    
    volume_driver: mydriver
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    1. volumes_from
      从其它容器或者服务挂载数据卷,可选的参数是 :ro或者 :rw,前者表示容器只读,后者表示容器对数据卷是可读可写的。默认情况下是可读可写的。
    volumes_from:
      - service_name
      - service_name:ro
      - container:container_name
      - container:container_name:rw
    
    • 1
    • 2
    • 3
    • 4
    • 5
    1. cap_add, cap_drop
      添加或删除容器的内核功能。详细信息在前面容器章节有讲解,此处不再赘述。
    cap_add:
      - ALL
    
    cap_drop:
      - NET_ADMIN
      - SYS_ADMIN
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    1. cgroup_parent
      指定一个容器的父级cgroup。
    cgroup_parent: m-executor-abcd
    
    • 1
    1. devices
      设备映射列表。与Docker client的–device参数类似。
    devices:
      - "/dev/ttyUSB0:/dev/ttyUSB0"
    
    • 1
    • 2
    1. extends
      这个标签可以扩展另一个服务,扩展内容可以是来自在当前文件,也可以是来自其他文件,相同服务的情况下,后来者会有选择地覆盖原有配置。
    extends:
      file: common.yml
      service: webapp
    
    • 1
    • 2
    • 3

    用户可以在任何地方使用这个标签,只要标签内容包含file和service两个值就可以了。file的值可以是相对或者绝对路径,如果不指定file的值,那么Compose会读取当前YML文件的信息。

    1. network_mode
      网络模式,与Docker client的–net参数类似,只是相对多了一个service:[service name] 的格式。
      例如:
    network_mode: "bridge"
    network_mode: "host"
    network_mode: "none"
    network_mode: "service:[service name]"
    network_mode: "container:[container name/id]"
    
    • 1
    • 2
    • 3
    • 4
    • 5

    可以指定使用服务或者容器的网络。

    1. networks
      加入指定网络,格式如下:
    services:
      some-service:
        networks:
         - some-network
         - other-network
    
    • 1
    • 2
    • 3
    • 4
    • 5

    关于这个标签还有一个特别的子标签aliases,这是一个用来设置服务别名的标签,例如:

    services:
      some-service:
        networks:
          some-network:
            aliases:
             - alias1
             - alias3
          other-network:
            aliases:
             - alias2
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    相同的服务可以在不同的网络有不同的别名。

    1. 其它
      还有这些标签:cpu_shares, cpu_quota, cpuset, domainname, hostname, ipc, mac_address, mem_limit, memswap_limit, privileged, read_only, restart, shm_size, stdin_open, tty, user, working_dir
      上面这些都是一个单值的标签,类似于使用docker run的效果。
    cpu_shares: 73
    cpu_quota: 50000
    cpuset: 0,1
    
    user: postgresql
    working_dir: /code
    
    domainname: foo.com
    hostname: foo
    ipc: host
    mac_address: 02:42:ac:11:65:43
    
    mem_limit: 1000000000
    memswap_limit: 2000000000
    privileged: true
    
    restart: always
    
    read_only: true
    shm_size: 64M
    stdin_open: true
    tty: true
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    Docker 安装 Redis

    拉取最新镜像

    docker pull redis:latest
    
    • 1

    查看本地镜像

    docker images
    
    • 1

    运行容器

    其中fymod-redis可以任意命名。

    docker run -itd --name fymod-redis -p 6379:6379 redis
    
    • 1

    查看运行

    docker ps
    
    • 1

    测试

    先连接上

    docker exec -it fymod-redis /bin/bash
    
    • 1

    使用命令redis-cli测试,添加key如set test 123321

    Docker 安装 mysql

    拉取镜像

    docker pull mysql
    
    • 1

    查看镜像

    docker image ls
    
    • 1

    启动

    docker run --name fymod-mysql -e MYSQL_ROOT_PASSWORD=123456 -p 3306:3306 -d mysql
    
    • 1

    容器状态

    docker ps
    
    • 1

    远程连接

    运行docker ps查看到mysql对应的容器id

    docker exec -it 容器ID数值 /bin/bash
    mysql -uroot -p123456 // 123456是密码
    mysql> ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY '123456';
    
    • 1
    • 2
    • 3
  • 相关阅读:
    【C语言】深入解析选择排序算法
    【UCB操作系统CS162项目】Pintos Lab2:用户程序 User Programs(上)
    赚够钱回老家吗
    Prefix-Tuning源码解析
    简单认识 .sync、inheritAttrs和attrs
    docker安装redis详细教程
    2023中国高校计算机大数据挑战赛:论文学科分类baseline|清华主办
    使用IntelliJ IDEA创建Maven项目并上传项目至gitlab等远程仓库
    HTML5 跨屏前端框架 Amaze UI
    Frechet distance距离计算原理及python实现
  • 原文地址:https://blog.csdn.net/m0_58095675/article/details/126638048