美文网首页
深入理解docker原理

深入理解docker原理

作者: voidFan | 来源:发表于2021-03-30 21:33 被阅读0次

    docker

    Docker通过一个包括应用程序运行时所需的一切的可执行镜像启动容器,包括代码、运行时库文件、环境变量和配置文件等。
    1.文件系统隔离:每个容器都有自己得root文件系统。
    2.进程隔离:每个容器都运行在自己独立的进程环境中。
    3.容器间的虚拟网络接口和IP地址都是分开的。
    4.资源隔离和分组:使用cgroup将CPU和内存之类的资源独立分配给每个Docker容器。
    5.写时复制:文件系统都是通过写时复制创建的,这就意味着文件系统是分层的、快速的,并且占用磁盘空间小。
    6.日志:容器产生的STDOUT、STDIN和STDERR这些IO流都会被收集并记入日志,用来进行日志分析和故障排除。
    7.交互式shell:用户可以创建一个伪tty终端、将其连接到STDIN,为容器提供一个交互式shell。
    8.灵活性:大多数应用程序均能被装箱。
    9.轻量级:容器利用并共享主机内核。
    10.可交互:可以即时的更新和升级。
    11.可移植:一处构建,到处运行。
    12.可扩展性:可以增加和分发容器副本。

    docker
    Docker 源码分析

    docker镜像制作

    • 查看docker进程状态
    systemctl status docker #查看docker的服务状态
    systemctl start docker  #启动 docker 服务
    
    • 获取base镜像(以centos为例)
    docker search centos
    docker pull centos
    docker images         # 查看镜像
    
    • 通过镜像创建容器
    docker run -tid --name=<容器名> <image_id> /bin/bash  # 创建容器并运行
    docker ps -a                                         # 查看所有容器的基本信息
    docker inspect <container_id>                        # 查看容器详情
    docker exec -it <容器名> /bin/bash                    # 进入容器
    exit       #退出容器
    
    • 容器创建
    # 将容器打包制作成镜像
    docker commit -m '镜像描述' -a '制作者' <容器名> <制作后的镜像名>  #制作镜像
    # 将制作好的镜像打成 tar 包
    docker save -o <tar包的名字> <镜像名>
    # tar包的使用
    docker load < tar包所在路径  #
    docker images               # 查看加载的镜像
    

    docker容器的生命周期

    • 创建一个容器的主要步骤
    1. docker pull xxx  #拉取镜像
    2. docker create    #创建一个容器(未启动)
    3. 为容器分配文件系统
    4. 为容器创建网络
    5. 启动容器
    

    容器间基于 --link 的单向通信

    # 1、启动一个数据库容器
    docker run -dti --name <mydb> redis
    # 2、启动一个web服务
    docker run --name <myweb> --link mydb -dti centos
    # 3、进入web容器
    docker exec -ti <contain_id> /bin/bash
    # 4、在容器ping
    ping mydb
    

    容器间利用 brige 网桥实现双向通信

    # 1、查看当前网桥 
    docker network ls
    # 2、创建一个新的my-bridge网桥
    docker network create -d bridge my-bridge
    # 3、将远行的容器加入到网桥my-bridge
    docker network connect my-bridge app1
    docker network connect my-bridge app2
    docker network connect my-bridge app3
    # 4、在app1容器中,可以ping app2
    ping app2
    

    Volume数据共享

    docker run 时用 -v 宿主机目录:容器中的目录
    docker run -it -v /宿主机绝对路径目录:/容器内目录:ro 镜像名 【带权限】

    创建webpage的容器卷 (/usr/local/tomcat/webapps)

    docker create --name webpage -v 宿主机目录:容器中的目录 tomcat /bin/true

    docker run -dti -p 8001:8080 --volumes-from webpage --name tomcat1 tomcat /bin/bash
    docker run -dti -p 8002:8080 --volumes-from webpage --name tomcat2 tomcat /bin/bash
    docker run -dti -p 8003:8080 --volumes-from webpage --name tomcat3 tomcat /bin/bash

    docker_compose安装

    单机容器编排工具

    Docker Login命令用于登陆Docker Registry

    登陆成功Docker会将token存储在~/.docker/config.json文件中,从而作为拉取私有镜像的凭证。

    # docker login [option] [server]
    option列表如下:
        --password, -p:密码
        --password-stdin:从标准输入中读取密码
        --username, -u:用户名
    eg:
    docker login --username=cheergoivan registry.cn-hangzhou.aliyuncs.com
    

    docker实现原理

    • Namespaces:主要起隔离作用
      1. pid namespace:进程隔离
      2. net namespace:网络管理
      3. ipc namespace:IPC(进程间通信)资源管理
      4. mnt namespace:文件系统挂载管理
      5. uts namespace:内核和版本标识符隔离。
    • Control groups:控制组(限制容器对物理资源的使用,eg:cpu、内存)
    • UnionFS:联合文件系统(为容器提供块功能,也就是文件系统)
    • Container format:容器格式

    Dockerfile 文件怎么写

    FROM tomcat:latest           # 利用FROM命令设置基准镜像
    WORKDIR /usr/local/workdir   # cd /usr/local/workdir
    ADD test.tar.gz /            # 添加文件到根目录并自动解压
    ADD docker_web ./            # ADD用于复制本地文件到镜像中, ADD除了复制,还具备添加远程文件功能
    EXPOST 8080                  # docker run -p 8000:8080 tomcat
    ENV JAVA_HOME /usr/local/openjdk8
    RUN $(JAVA_HOME)/bin/java-jar xxx.jar  # 在docker build 构建时执行的命令
    ENTRYPOINT ["ps"]                      # docker run 容器启动时执行的命令
    CMD ["-ef"]                            # docker run 容器运行后执行的默认的命令或参数
    

    docker源码解析

    • docker源码目录下有docker-engine、docker-ce、cli等子项目。
    • docker-ce的components下也有cli,engine和packaging。
    • 发现docker-ce下的cli和engine与docker家目录下得docker-engine和cli是一样得。也就是docker-ce只是组合了docker-engine,cli等。
      1. 如何生成命令行供我们使用?
      2. 在调用命令行后,如何访问到docker server 提供的 restful api?
      3. docker engine 一定在监听 restful api 对应的地址!
      4. docker engine 收到指令,接下来如何执行
    • 命令行模块的入口:docker-ce/components/cli/cmd/docker/docker.go
    • 每个具体的命令实现:docker-ce/components/cli/cli/command (如:image镜像相关,container容器相关)
    • 排查容器启动流程,当然去container目录下,可以看到容器相关命令对应的文件start.go
    package main
    import (
        "github.com/spf13/cobra"  //命令行功能依赖的三方库
    )
    func runStart(dockerCli command.Cli, opts *startOptions) error {
        //TODO:利用cobra包解析后,命令行访问docker server提供的restful api
        return dockerCli.Client().ContainerStart(ctx, container, startOptions)
    }
    func NewStartCommand(dockerCli command.Cli) *cobra.Command {
        //TODO:
        return runStart(dockerCli, &opts)
    }
    
    • dockerCli指向 docker/engine/client/container_start.go:ContainerStart方法, 访问restful api的封装方法。
    func (cli *Client) ContainerStart(ctx context.Context, containerID string, options types.ContainerStartOptions) error {
        //TODO:ContainerStart 方法调用的是 cli.post
    }
    
    • 服务端找到监听这个地址的方法是如何处理的。
    • docker server的入口函数在 engine目录下: docker.go
    • 再看路由的定义 components/engine/api/server/router/container/container.go
    func (r *containerRouter) initRouter() {
        r.routes = []router.Route{
            router.NewPostRoute("/containers/create", r.postContainersCreate),
        }
    }
    
    • 分析postContainersCreate方法中的关键方法是:s.backend.ContainerCreate()
    • engine/api/server/router/container/backend.go 中可以找到 ContainerStart的接口定义
    • ContainerStart真正的定义在components/engine/daemon/start.go中可以看到daemon.containerStart()

    docker 应用

    mysql安装部署

    docker pull mysql
    docker run -di --name mysqlServer -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 mysql
    docker exec -it <CONTAINER ID> /bin/bash  # 进入mysql
    mysql -u root -p123456                    # 登陆
    

    nginx部署

    docker pull nginx
    docker run -di --name=nginxServer -p 80:80  nginx
    

    redis部署

    docker pull redis
    docker run -di --name=rediServer -p 6379:6379 redis
    redis-cli   # 可进入client
    

    postgres部署

    docker pull postgres    # 拉取Postgresq镜像
    # 构建镜像容器
    docker run -it --name postgres --restart always -e POSTGRES_PASSWORD='123456' -e ALLOW_IP_RANGE=0.0.0.0/0 -v /home/postgres/data:/var/lib/postgresql -p 5432:5432 -d postgres
    docker exec -it postgres bash      # 进入postgres容器
    su postgres                        # 切换当前用户,再登录数据库
    psql -U postgres -W                # 设置pg的密码
    

    基于docker-compose部署ElasticSearch集群(单机多节点)

    1、安装前准备(问题:bootstrap checks failed)

    
    grep vm.max_map_count /etc/sysctl.conf # 查看vm.max_map_count命令
    vm.max_map_count=262144                # 内核设置需要至少设置为262144用于生产
    sysctl -w vm.max_map_count=262144      # 设置实时生效
    
    docker pull openjdk:9  # ElasticSearch是基于java, 
    docker pull openjdk:11 # 需要支持LTS,jdk9以上才支持
    

    2、部署(在/home/elasticsearch下创建docker-compose.yml)

    version: '2.2'
    services:
      es01:
        image: docker.elastic.co/elasticsearch/elasticsearch:7.4.0
        container_name: es01
        environment:
          - node.name=es01
          - discovery.seed_hosts=es02
          - cluster.initial_master_nodes=es01,es02
          - cluster.name=docker-cluster
          - bootstrap.memory_lock=true
          - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
        ulimits:
          memlock:
            soft: -1
            hard: -1
        volumes:
          - esdata01:/usr/share/elasticsearch/data
        ports:
          - 9200:9200
        networks:
          - esnet
      es02:
        image: docker.elastic.co/elasticsearch/elasticsearch:7.4.0
        container_name: es02
        environment:
          - node.name=es02
          - discovery.seed_hosts=es01
          - cluster.initial_master_nodes=es01,es02
          - cluster.name=docker-cluster
          - bootstrap.memory_lock=true
          - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
        ulimits:
          memlock:
            soft: -1
            hard: -1
        volumes:
          - esdata02:/usr/share/elasticsearch/data
        networks:
          - esnet
    
    volumes:
      esdata01:
        driver: local
      esdata02:
        driver: local
    
    networks:
      esnet:
    

    3、执行docker-compose up

    4、基本功能验证

    curl http://127.0.0.1:9200/_cat/health      # 检查集群状态
    curl http://localhost:9200/_cluster/health  # 查看集群健康
    curl http://localhost:9200/_nodes?pretty    # 查看节点信息
    docker logs -f es01   # 查看 es01节点的日志
    
    docker restart es01  && docker restart es02  # 修改config/elasticsearch.yml后重启
    

    相关文章

      网友评论

          本文标题:深入理解docker原理

          本文链接:https://www.haomeiwen.com/subject/xucnhltx.html