• docker学习笔记


    docker简介

    docker安装

    dockerRun流程

    docker安装mysql

    docker安装nginx

    docker容器数据卷技术

    dockerFile

    部署redis集群

    docker compose

    1.docker简介

    1.docker官网:https://www.docker.com/

    2.docker是什么

    ​ Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的 LinuxWindows 机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。

    ​ Docker采用 C/S架构 ,Docker daemon 作为服务端接受来自客户的请求,并处理这些请求(创建、运行、分发容器)。 客户端和服务端既可以运行在一个机器上,也可通过 socket 或者restful API 来进行通信。

    docker主要分为3部分组成:客户端、服务器、仓库;客户端命令docker内部的守护进程执行结果,并将结果返回给客户端。

    docker build :构建容器

    docker pull : 拉取容器

    docker run : 运行容器

    docker daemon :docker守护线程

    docker镜像(image):其实就是模板,可以通过这个模板来创建容器服务,通过镜像可以创建多个容器,最终服务运行或者项目运行在容器中

    容器(container):docker利用容器技术,独立运行一个或者一组应用,通过镜像来创建的

    仓库(repository):仓库是存放镜像的地方,分为共有仓库和私有仓库

    3.docker能干什么

    ​ 1.更快速的交付和部署
    ​ 2.更便捷的升级或扩缩容
    ​ 3.更简单的系统运维
    ​ 4.更高效的计算资源利用

    4.docker与虚拟机对比

    docker 虚拟机
    操作系统 与宿主机共享OS 在宿主机OS上运行
    存储大小 镜像小,便于存储和传输 镜像庞大(如centos的vmdk至少900多M)
    运行性能 几乎无额外性能损失 操作系统额外的cpu,内存消耗大
    移植性 轻便灵活,适用于Linux 笨重,与虚拟化技术耦合度高
    硬件亲和性 面向开发人员 面向硬件运维者

    docker有比虚拟机更少的抽象层

    docker利用的是宿主机的内核,而不需要Guest OS

    2.docker安装

    #系统内核查看
    [root@localhost ~]# uname -r
    #系统版本查看
    [root@localhost ~]# cat /etc/os-release
    #安装需要的安装包
    yum install -y yum-utils
    # 设置阿里云的镜像仓库
    yum-config-manager 
    	--add-repo 
    	https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo	
    # 更新yum的软件包
    [root@localhost /]# yum makecache fast
    #安装最新版本的 Docker Engine-Community 和 containerd,
    yum install docker-ce docker-ce-cli containerd.io
    #启动docker
    [root@localhost /]# systemctl start docker
    
    #配置阿里云镜像加速,注册阿里云的账号,然后产品->容器与中间件->容器镜像服务 ACR->管理控制台->镜像加速器->CentOS
    # 按照上面的步骤配置
    [root@localhost ~]# mkdir -p /etc/docker
    [root@localhost ~]# tee /etc/docker/daemon.json <<-'EOF'
     {
       "registry-mirrors": ["https://fz0dvm3j.mirror.aliyuncs.com"]
     }
     EOF
    [root@localhost ~]# systemctl daemon-reload
    [root@localhost ~]# systemctl restart docker
    

    3.dockerRun流程

    # 启动docker完成,run  hello-world
    [root@localhost /]# docker run hello-world
    #没有寻找到这个镜像
    Unable to find image 'hello-world:latest' locally  
    #这里的pull就是去远程拉取镜像
    latest: Pulling from library/hello-world 
    #拉取完成
    0e03bdcc26d7: Pull complete  
    Digest: sha256:e7c70bb24b462baa86c102610182e3efcb12a04854e8c582838d92970a09f323
    Status: Downloaded newer image for hello-world:latest
    Hello from Docker! 
    

    从上面的run流程可以归纳出这样的一张图:

    镜像删除:docker rmi hello-world(镜像名)

    删除正在运行的容器:docker rmi -f hello-world(镜像名)

    删除所有的容器:docker rm -f $(docker ps -aq)

    4.docker安装mysql

    # 拉取官方mysql, 指定版本docker pull mysql:5.7,也可以直接使用docker run mysql,参考上面run的流程,默认是最新版本 mysql:latest
    [root@localhost ~]# docker pull mysql:5.7
    # 查看安装了哪些镜像
    [root@localhost ~]# docker images
    # 安装完成后,运行容器
    # 参数说明:--name 给容器命名
    # -p 3306:3306 :映射容器服务的 3306 端口到宿主机的 3306 端口,外部主机可以直接通过 宿主机ip:3306 访问到 MySQL 的服务。
    # MYSQL_ROOT_PASSWORD=123456:设置 MySQL 服务 root 用户的密码。
    [root@localhost ~]# docker run -itd --name mysql-test -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 mysql
    # docker ps 命令查看是否安装成功
    [root@localhost ~]# docker ps
    CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                               NAMES
    a40c92638f4d        mysql               "docker-entrypoint.s…"   22 seconds ago      Up 20 seconds       0.0.0.0:3306->3306/tcp, 33060/tcp   mysql-test
    # 进入容器
    [root@localhost ~]# docker exec -it mysql-test bash
    # 启动mysql ,root的密码为123456
    root@a40c92638f4d:/# mysql -u root -p
    

    进入容器的方式:

    # 进入容器后开启一个新的终端,可以在里面操作
    docker exec -it mysql-test bash
    # 进入正在执行当前的代码,不会启动新的进程
    docker attach 容器id  
    

    退出当前容器,可以使用ctrl+p+q,不关闭容器退出,docker inspect (容器id),查看容器的所有信息;

    退出容器:exit

    停止容器:docker stop <容器 ID>

    停止的容器重启:docker restart <容器 ID>

    5.docker 安装nginx

    [root@localhost ~]# docker pull nginx
    # 启动nginx
    # 参数说明:
    # -p 8080:80: 端口进行映射,将本地 8080 端口映射到容器内部的 80 端口。
    # -d nginx: 设置容器在在后台一直运行。
    [root@localhost ~]# docker run --name nginx-test -p 8080:80 -d nginx
    

    在浏览器上查看(出现这个页面即表示成功):

    6.docker容器数据卷技术

    在项目中,对数据的要求是能持久化的,容器之间希望有可能共享数据;为了能把数据保存在docker中,就产生了数据卷技术。

    测试数据卷

    # 命名为第一个窗口
    [root@localhost ~]# docker pull centos
    # 创建测试目录
    [root@localhost ~]# mkdir /home/test
    # 挂载
    [root@localhost test]# docker run -it -v /home/test:/home centos /bin/bash
    
    # 另起一个窗口,命名为第二个窗口,查看是否挂载成功
    [root@localhost ~]# docker ps
    CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
    f362100fe4ab        centos              "/bin/bash"         3 minutes ago       Up 3 minutes                            happy_thompson
    [root@localhost ~]# docker inspect f362100fe4ab
    # 这是与挂载有关的内容(默认有挂载)
    "Mounts": [
                {
                    "Type": "bind",
                    "Source": "/home/test",
                    "Destination": "/home",
                    "Mode": "",
                    "RW": true,
                    "Propagation": "rprivate"
                }
            ]
    
    # 在第一个窗口,挂载成功就进入了centos的镜像中
    [root@f362100fe4ab /]# ls 
    bin  etc   lib	  lost+found  mnt  proc  run   srv  tmp  var
    dev  home  lib64  media       opt  root  sbin  sys  usr
    [root@f362100fe4ab /]# cd /home
    # 可以看到镜像里面的home目录下什么内容都没有,新建一个Test.java文件
    [root@f362100fe4ab home]# ls
    [root@f362100fe4ab home]# touch Test.java
    
    # 第二个窗口的挂载test挂载的目录下,可以看到有也有一个Test.java的文件
    [root@localhost ~]# cd /home/test
    [root@localhost test]# ls
    Test.java
    

    如果在容器外(即第二个窗口)修改内容,在容器里还是可以同步看到修改的内容,就算容器关闭了,在外面修改了,还是会同步到容器里的。

    测试mysql数据永久化

    [root@localhost home]# mkdir mysql
    [root@localhost home]# ls
    mysql  test
    [root@localhost home]# cd mysql
    [root@localhost mysql]# mkdir conf
    [root@localhost mysql]# cd conf
    # 挂载并启动 -v:虚拟机目录:容器目录(挂载目录)	
    [root@localhost test]# docker run -d -p 3306:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql-test mysql
    
    # 在docker虚拟机内挂载mysql的data目录对应的挂载目录下可以看到里面有了mysql的文件
    [root@localhost test]# cd /home/mysql/data
    [root@localhost data]# ls
    auto.cnf       client-cert.pem    ib_logfile0   performance_schema  undo_001
    binlog.000001  client-key.pem     ib_logfile1   private_key.pem     undo_002
    binlog.000002  #ib_16384_0.dblwr  ibtmp1        public_key.pem
    binlog.index   #ib_16384_1.dblwr  #innodb_temp  server-cert.pem
    ca-key.pem     ib_buffer_pool     mysql         server-key.pem
    ca.pem         ibdata1            mysql.ibd     sys
    

    关闭防火墙:systemctl stop firewalld

    打开navicat 连接数据库并测试:

    新建一个数据库:docker_test01,下图可以看到,在data文件下多了一个docker_test01的文件

    如果我们将容器删除,发现我们挂载到本地的数据卷依旧没有丢失;这就实现了我们容器数据持久化的功能;

    7.DockerFile

    Dockerfile 是一个用来构建镜像的文本文件,文本内容包含了一条条构建镜像所需的指令和说明。Docker就是通过读取Dockerfile中的指令自动生成映像;

    使用dockerfile定制一个镜像

    # 在home下创建一个dockerfile_test01的文件夹
    [root@localhost home]# mkdir dockerfile_test01
    [root@localhost home]# cd dockerfile_test01/
    [root@localhost dockerfile_test01]# ls
    [root@localhost dockerfile_test01]# vi dockerfile
    # 编写dockerfile的命令
    FROM centos:latest
    
    VOLUME ["volume01","volume02"]
    CMD echo "-------------centos end------"
    
    CMD /bin/bash
    # 构建镜像
    # -f:表示文件的地址(默认是dockerfile,可以不写)  -t target,生成的意思,  .表示生成在当前目录下
    [root@localhost dockerfile_test01]# docker build -f dockerfile -t charon/centos .
    Sending build context to Docker daemon  2.048kB
    Step 1/4 : FROM centos:latest
     ---> 0d120b6ccaa8
    Step 2/4 : VOLUME ["volume01","volume02"]
     ---> Running in cf7a5a93a2a4
    Removing intermediate container cf7a5a93a2a4
     ---> f126dd1ad5d2
    Step 3/4 : CMD echo "-------------centos end------"
     ---> Running in c2f6af5454a7
    Removing intermediate container c2f6af5454a7
     ---> 5bfaded00378
    Step 4/4 : CMD /bin/bash
     ---> Running in f264651260c2
    Removing intermediate container f264651260c2
     ---> 5c32c0037c47
    Successfully built 5c32c0037c47
    Successfully tagged charon/centos:latest
    
    # dockerfile构建成功后,查看容器内容
    [root@localhost data]# docker inspect d8c483d4873d(为CONTAINER ID )
    

    8.部署redis集群

    # 建立redis网卡
    [root@localhost ~]# docker network create redis --subnet 172.25.0.0/16
    abc2557e81e375c4f354a015685f6ec0d29b6abc40ec841bcbd6005e797a4c92
    # 查看所有的网络
    [root@localhost ~]# docker network ls
    NETWORK ID          NAME                DRIVER              SCOPE
    73ee4682decf        bridge              bridge              local
    617ed0ba638f        host                host                local
    310d6730eaf1        none                null                local
    abc2557e81e3        redis               bridge              local
    # 查看redis的网卡信息
    [root@localhost redis]# docker network inspect redis
    [
        {
            "Name": "redis",
            "Id": "abc2557e81e375c4f354a015685f6ec0d29b6abc40ec841bcbd6005e797a4c92",
            "Created": "2020-12-07T22:01:35.743996656+08:00",
            "Scope": "local",
            "Driver": "bridge",
            "EnableIPv6": false,
            "IPAM": {
                "Driver": "default",
                "Options": {},
                "Config": [
                    {
                        "Subnet": "172.25.0.0/16"
                    }
                ]
            },
            "Internal": false,
            "Attachable": false,
            "Ingress": false,
            "ConfigFrom": {
                "Network": ""
            },
            "ConfigOnly": false,
            "Containers": {},
            "Options": {},
            "Labels": {}
        }
    ]
    [root@localhost redis]# cd /
    # 创建redis脚本节点(这里使用三主三从,reids集群至少要三个主节点)
    [root@localhost /]# for port in $(seq 1 6); 
     do 
     mkdir -p /redis/node-${port}/conf
     touch /redis/node-${port}/conf/redis.conf
     cat << EOF >/redis/node-${port}/conf/redis.conf
     port 6379 
     bind 0.0.0.0
     cluster-enabled yes 
     cluster-config-file nodes.conf
     cluster-node-timeout 5000
     cluster-announce-ip 172.25.0.1${port}
     cluster-announce-port 6379
     cluster-announce-bus-port 16379
     appendonly yes
     EOF
     done
    [root@localhost /]# ls
    bin  boot  dev  etc  home  lib  lib64  media  mnt  mydata  opt  proc  redis  root  run  sbin  srv  sys  tmp  usr  var
    [root@localhost /]# cd mydata/redis
    [root@localhost redis]# ls
    node-1  node-2  node-3  node-4  node-5  node-6
    [root@localhost redis]# cd /
    # 启动redis的脚本
    [root@localhost /]#  for port in $(seq 1 6);
    do 
    docker run -p 637${port}:6379 --name redis-${port} 
    -v /mydata/redis/node-${port}/data:/data 
    -v /mydata/redis/node-${port}/conf/redis.conf:/etc/redis/redis.conf 
    -d --net redis --ip 172.25.0.1${port} redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
    done
    # 可以使用 docker ps -a  查看启动的redis
    
    # 进入redis-1容器
    [root@localhost /]# docker exec -it redis-1 /bin/sh
    # 创建集群 (--cluster-replicas 1 :为集群中的每个主节点创建一个从节点)
    /data # redis-cli --cluster create 172.25.0.11:6379 172.25.0.12:6379 172.25.0.13:6379 172.25.0.14:6379 172.25.0.15:6379 172.25.0.16:6379 --cluster-replicas 1
    
    # 连接集群(redis-cli单机,-c是集群)
    /data # redis-cli -c
    # 可以看到三主三从一一对应的
    127.0.0.1:6379> cluster nodes
    b3a8f84b35f7efbac7058ae39fd7119d3da76e0b 172.25.0.11:6379@16379 myself,master - 0 1607353015000 1 connected 0-5460
    aac8da4b1adcf81ed1daa7eab82c0f7e74f38e43 172.25.0.16:6379@16379 slave b21c59b5a169ede19bdacb6aa0ee563678e2d4cd 0 1607353015556 6 connected
    b21c59b5a169ede19bdacb6aa0ee563678e2d4cd 172.25.0.12:6379@16379 master - 0 1607353016583 2 connected 5461-10922
    796f01b60f61f75775a83e39fd173f2bb2d26249 172.25.0.15:6379@16379 slave b3a8f84b35f7efbac7058ae39fd7119d3da76e0b 0 1607353017095 5 connected
    375a629a1dd989f47a1522ddf8f18930d56b7e92 172.25.0.14:6379@16379 slave 065734d0bc0a105639b91fd25310e7f6ef13a979 0 1607353016583 4 connected
    065734d0bc0a105639b91fd25310e7f6ef13a979 172.25.0.13:6379@16379 master - 0 1607353016584 3 connected 10923-16383
    
    # 往redis中设置一个值,可以看到,现在是存储在11这台redis上的
    172.25.0.13:6379> set charon 111
    -> Redirected to slot [1403] located at 172.25.0.11:6379
    OK
    # 另打开一个窗口,关闭掉redis-1的容器   docker stop redis-1
    # 重启redis集群
    /data # redis-cli -c
    # get a的值,可以看到,是从15这个redis上获取的,在我这里,15为11的从redis
    127.0.0.1:6379> get charon
    -> Redirected to slot [1403] located at 172.25.0.15:6379
    "111"
    

    9.docker compose

    compose是用于定义和运行多容器docker应用程序的工具。通过compose,可以使用yml文件来配置应用程序需要的所有服务,然后用一个命令,就可以从yml文件配置中创建并启动所有的服务。

    compose使用的三个步骤:

    1. 使用dockerfile定义应用程序的环境
    2. 使用docker-compsoe.yml定义构成应用程序的服务,这样他们可以在隔离环境中一起运行
    3. 执行docker-compose up 命令来启动并运行整个应用程序

    compose安装

    # 在github上下载,但是很慢,不推荐
    [root@localhost ~]# curl -L "https://github.com/docker/compose/releases/download/1.24.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
    # 这种方式下载很快
    [root@localhost ~]# curl -L https://get.daocloud.io/docker/compose/releases/download/1.25.5/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
    # 授权
    [root@localhost bin]# chmod +x /usr/local/bin/docker-compose
    # 能够看到版本信息,表示安装成功
    [root@localhost bin]# docker-compose version
    docker-compose version 1.25.5, build 8a1c60f6
    docker-py version: 4.1.0
    CPython version: 3.7.5
    OpenSSL version: OpenSSL 1.1.0l  10 Sep 2019
    

    配置

    [root@localhost home]# mkdir composetest
    [root@localhost home]# cd composetest
    [root@localhost composetest]# touch app.py
    # 编辑内容
    [root@localhost composetest]# vi app.py 
    
    import time
    
    import redis
    from flask import Flask
    
    app = Flask(__name__)
    cache = redis.Redis(host='redis', port=6379)
    
    
    def get_hit_count():
        retries = 5
        while True:
            try:
                return cache.incr('hits')
            except redis.exceptions.ConnectionError as exc:
                if retries == 0:
                    raise exc
                retries -= 1
                time.sleep(0.5)
    
    
    @app.route('/')
    def hello():
        count = get_hit_count()
        return 'Hello World! I have been seen {} times.
    '.format(count)
        
    # 创建requirements.txt文件
    root@localhost composetest]# vi requirements.txt 
    #requirements.txt文件内容
    flask
    redis
    # 创建dockerfile文件
    [root@localhost composetest]# vi dockerfile
    # dockerfile文件内容
    FROM python:3.7-alpine
    WORKDIR /code
    ENV FLASK_APP app.py
    ENV FLASK_RUN_HOST 0.0.0.0
    RUN apk add --no-cache gcc musl-dev linux-headers
    COPY requirements.txt requirements.txt
    RUN pip install -r requirements.txt
    COPY . .
    CMD ["flask", "run"]
    # 创建 docker-compose.yml
    [root@localhost composetest]# vi docker-compose.yml
    # yaml 配置
    version: '3'
    services:
      web:
        build: .
        ports:
         - "5000:5000"
      redis:
        image: "redis:alpine"
        
    # 启动应用程序,这一步需要的时间挺长
    [root@localhost composetest]# docker-compose up -d
    # 安装完成后,查看网络
    [root@localhost composetest]# docker network ls
    NETWORK ID          NAME                  DRIVER              SCOPE
    2cb20a237d9f        bridge                bridge              local
    c1ed15f1d7c0        composetest_default   bridge              local
    617ed0ba638f        host                  host                local
    310d6730eaf1        none                  null                local
    abc2557e81e3        redis                 bridge              local
    # 查看composetest_default的信息,从下面的Containers可以看到,redis和web都在同一个容器下
    [root@localhost composetest]# docker network inspect composetest_default
    [
        {
            "Name": "composetest_default",
            "Id": "c1ed15f1d7c0dc9b0ef1510242279478d186e01a164fe6999208d0fc8e3ac994",
            "Created": "2020-12-09T22:43:23.963784858+08:00",
            "Scope": "local",
            "Driver": "bridge",
            "EnableIPv6": false,
            "IPAM": {
                "Driver": "default",
                "Options": null,
                "Config": [
                    {
                        "Subnet": "172.18.0.0/16",
                        "Gateway": "172.18.0.1"
                    }
                ]
            },
            "Internal": false,
            "Attachable": true,
            "Ingress": false,
            "ConfigFrom": {
                "Network": ""
            },
            "ConfigOnly": false,
            "Containers": {
                "0aaadf14519bf27d01d8531f3c2a67f2cc3f6509374883a789724881fc117837": {
                    "Name": "composetest_web_1",
                    "EndpointID": "b42e5f64bdfdfa2227499f89ba7a18c10ef07bdfc36c8e1d5affef23d93b884e",
                    "MacAddress": "02:42:ac:12:00:03",
                    "IPv4Address": "172.18.0.3/16",
                    "IPv6Address": ""
                },
                "215f9ec5e5c15c0399374102550c5c3d6437385005050ebe6018e1aa4f6d3055": {
                    "Name": "composetest_redis_1",
                    "EndpointID": "a3700748c83e5a6a342b0f01a1fd9cbb72d1820c9eb1abdf97909c7073ca7b5b",
                    "MacAddress": "02:42:ac:12:00:02",
                    "IPv4Address": "172.18.0.2/16",
                    "IPv6Address": ""
                }
            },
            "Options": {},
            "Labels": {
                "com.docker.compose.network": "default",
                "com.docker.compose.project": "composetest",
                "com.docker.compose.version": "1.25.5"
            }
        }
    ]
    # 访问
    [root@localhost composetest]# curl http://localhost:5000
    Hello World! I have been seen 1 times.
    [root@localhost composetest]# curl http://localhost:5000
    Hello World! I have been seen 2 times.
    [root@localhost composetest]# curl http://localhost:5000
    Hello World! I have been seen 3 times.
    
    

    在浏览器中也可以使用ip+端口访问

    默认的服务名格式:文件名_格式名_1(number)

    compose自动维护了一个网络,项目中的内容都是同一个网络(域名)下,如上面app.py中配置的,cache = redis.Redis(host='redis', port=6379),这里的reids的ip(域名)都是redis,以后就可以通过redis:6379也可以访问。

    参考文档:

    https://www.runoob.com/docker/centos-docker-install.html (docker的参考手册)

    https://www.cnblogs.com/zuxing/articles/8780661.html

  • 相关阅读:
    别人走的路--2
    win7下80端口被(Pid=4)占用的解决方法
    实习第一天原来是配置环境
    api接口大全
    java计算两个日期之间相隔的天数
    【转】overload与override的区别
    Overload和Override的区别?
    浅析Java中的final关键字
    JAVA中的finalize()方法
    封装
  • 原文地址:https://www.cnblogs.com/pluto-charon/p/14118514.html
Copyright © 2020-2023  润新知