zoukankan      html  css  js  c++  java
  • Docker

    1. Docker安装

    1.1 Docker的基本组成

    镜像(image):

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

    容器(container):

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

    仓库(repository):

    仓库就是存放镜像的地方
    
    仓库分为公有仓库和私有仓库
    
    Docker Hub
    
    阿里云等等都有容器服务器(默认在国外,配置镜像加速)
    

    1.2 安装Dokcer

    环境准备

    1. 需要linux基础
    2. Centos7
    3. 使用软件进行远程连接

    环境查看

    # 系统内核是3.10以上的
    unmae -r
    
    # 系统版本
    cat /etc/os-release
    

    安装

    帮助文档

    # 1.卸载旧的版本
    yum remove docker 
                      docker-client 
                      docker-client-latest 
                      docker-common 
                      docker-latest 
                      docker-latest-logrotate 
                      docker-logrotate 
                      docker-engine
                      
    # 2.需要的安装包
    yum install -y yum-utils
    
    # 3.设置镜像的仓库
    yum-config-manager 
        --add-repo 
        https://download.docker.com/linux/centos/docker-ce.repo  # 默认是国外的,需要换成国内的
        
    yum-config-manager 
        --add-repo 
        https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
        
    # 更新yum软件包索引
    yum makecache fast
    
    # 4. 安装docker相关的   docker-ce 社区版 ee企业版
    yum install docker-ce docker-ce-cli containerd.io
    
    # 5.启动docker
    systemctl start docker
    
    # 6.使用docker version测试是否安装成功
    docker version
    
    # 7.hello-word
    docker run hello-word
    
    # 8.查看下载的这个hello-word镜像
    docker images
    

    1.3 卸载docker

    # 1.卸载依赖
    yum remove docker-ce docker-ce-cli containerd.io
    
    # 2.删除资源
    rm -rf /var/lib/docker
    
    # /var/lib/docker docker的默认工作路径
    

    1.4 阿里云镜像加速

    1. 登录阿里云找到容器服务

    2. 找到镜像加速的地址

    3. 配置应用

      mkdir -p /etc/docker
      # 编辑daemon.json
      tee /etc/docker/daemon.json <<-'EOF'
      # 设置加速器地址
      {
        "registry-mirrors": ["https://xxxxxxxx.mirror.aliyuncs.com"]
      }
      EOF
      # 最后重新加载和重启docker:
      systemctl daemon-reload
      
      systemctl restart docker
      
      mkdir -p /etc/docker
      tee /etc/docker/daemon.json <<-'EOF'
      {
        "registry-mirrors": ["https://me0kxh75.mirror.aliyuncs.com"]
      }
      EOF
      systemctl daemon-reload
      systemctl restart docker
      

    1.5 run流程

    1.6 底层原理

    docker是怎么工作的?

    Docker 是一个client-server 结构的系统,Docker的守护进程运行在主机上,通告Socker从客户端访问

    Dokcer server 接收到Docker-client 的指令,就会执行这个命令

    Docker为什么比虚拟机快

    • Docker有着比虚拟机更少的抽象层
    • Docker 利用的是宿主机的内核,VM需要Guest OS
    • 所以,新建一个容器的时候,Docker不需要虚拟机一样重新加载一个操作系统的内核,避免引导。虚拟机是加载Guest OS,分钟级别的,而docker是利用宿主机的操作系统,省略了这个复杂的过程,秒级

    2. Docker常用命令

    2.1 帮助命令

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

    2.2 镜像命令

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

    docker images
    
    # 解释
    REPOSITORY  镜像的仓库源
    TAG			镜像的标签
    IMAGE ID	镜像的ID
    CREATED		镜像的创建时间
    SIZE		镜像的大小
    
    # 可选项
    -a  # 列出所有的镜像
    -q  # 只显示镜像的ID
    

    2.2.2 docker search 搜索镜像

    docker search mysql
    
    # 可选项
    --filter=STARS=3000   #搜索出来的镜像是STARS大于3000的
    

    2.2.3 docker pull 下载镜像

    # 下载镜像
    docker pull 镜像名[:tag]
    
    如果不写tag,默认就是latest
    分层下载,docker image的核心,联合文件系统
    Digest #签名
    docker.io/library/mysql:latest  #真实地址
    
    #等价于他
    docker pull mysql
    docker pull docker.io/library/mysql:latest
    
    # 指定版本下载
    docker pull mysql:5.7
    

    2.2.4 docker rmi 删除镜像

    docket rmi -f 镜像id  #删除指定镜像
    docket rmi -f 镜像id 镜像id  #删除多个镜像
    docket rmi -f $(docker images -aq)  #递归删除所有镜像
    

    2.3 容器命令

    说明:我们有了镜像才可以创建容器,Linux,下载一个centos 镜像来测试学习

    docker pull centos
    

    2.3.1 新建容器并启动 run

    docker run [可选参数] image
    
    # 参数说明
    --name="Name"   # 容器名字  tomcat01 tomcat02,用来区分容器
    -d				# 后台方式运行
    -it 				# 使用交互方式运行,进入容器查看内容
    -p				# 指定容器的端口 -p 8080:8080
    	-p ip:主机端口:容器端口
    	-p 主机端口:容器端口(常用)
    	-p 容器端口
    	容器端口
    -p				# 随机指定端口
    
    # 测试
    docker run -it centos /bin/bash  # 启动并进入容器
    	exit # 从容器中退回到主机
    

    2.3.2 docker ps 列出所有运行的容器

    docker ps  # 列出当前正在运行的容器
    
    -a  # 列出当前正在运行的容器+历史运行过的容器
    -n=?  # 显示最近创建的容器,例如-n=1,显示最近创建的一个容器
    -q  # 只显示容器的编号
    

    2.3.3 退出容器

    exit   # 直接容器停止并退出
    ctrl+p+q  #容器不停止退出
    

    2.3.4 删除容器 rm

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

    2.3.5 启动和停止容器的操作

    docker start 容器id         # 启动容器
    docker restart 容器id		  # 重启容器
    docker stop 容器id		  # 停止当前正在运行的容器
    docker kill 容器id		  # 强制停止当前容器
    

    2.4 常用其他命令

    2.4.1 后台启动容器

    # 命令 docker run -d 镜像名
    docker run -d centos
    
    # 问题 docker ps 发现centos停止了
    
    # 常见的坑,docker 容器使用后台运行,就必须要有一个前台进程,docker发现没有应用,就会自动停止
    # nginx,容器启动后,发现自己没有提供服务,就会立刻停止,就是没有程序了
    

    2.4.2 查看日志

    docker logs 
    # 显示日志
    -tf   #显示全部日志
    --tail number #显示指定数量的日志
    
    docker logs -f -t --tail 容器id   # 没有日志
    
    #自己编写一段shell脚本
    docker run -d centos /bin/bash -c "while true;do echo zjc;sleep 1;done"
    
    docker logs -tf --tail 10 容器id   
    

    2.4.3 查看容器中进程信息 ps

    # 命令 docker top容器id
    

    2.4.4 查看镜像的元数据 inspect

    docker inspect 容器id
    

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

    # 我们通常容器都是使用后台方式运行的,需要进入容器,修改一些配置
    
    #命令
    # 方式一
    docker exec -it 容器id /bin/bash
    
    # 方式二xi
    docker attach 容器id
    
    #区别
    docker exec #进入容器之后开启一个新的终端,可以在里面操作(常用)
    docker attach # 进入容器正在执行的终端,不会启动新的进程
    

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

    docker cp 容器id:容器内路径 目的地主机路径
    #拷贝是一个手动过程,可以使用-v卷的技术,可以实现
    

    2.5 常用命令小结

    attach					# 当前shell下attach连接指定运行镜像
    build					# 通过dockerfile定制镜像
    commit					# 提交当前容器为新的镜像
    cp					# 从容器中拷贝指定文件或者目录到宿主机中
    create					# 创建一个新的容器,同run 但不启动容器
    diff					# 查看docker 容器变化
    events					# 从docker 服务获取容器实时事件
    exec					# 在已存在的容器上运行命令
    export					# 导出容器的内容作为一个 tar 归档文件[对应import]
    history					# 展示一个镜像形成历史
    images					# 列出系统当前镜像
    import        			        # 从tar包中的内容创建一个新的文件系统映像[对应export]
    info					# 显示系统相关信息
    inspect					# 查看容器详细信息
    kill					# kill 指定容器
    load					# 从一个tar 包中加载一个镜像[对应save]
    login 					# 注册或者登陆一个docker源服务器
    logout					# 从当前docker registry退出
    logs					# 输出当前容器日志信息
    port					# 查看映射端口对应的容器内部源端口
    pause     				# 暂停容器
    ps					# 列出容器列表
    pull					# 从docker镜像源服务器拉取指定镜像或者库镜像
    push					# 推送指定镜像或者库镜像至docker源服务器
    restart					# 重启运行的容器
    rm					# 移除一个或者多个容器
    rmi					# 移除一个或多个镜像[无容器使用该镜像才可删除,否则需要删除相关容器才可继续或 -f 强制删除]
    run 					# 创建一个新的容器并运行一个命令
    save					# 保存一个镜像为一个tar包[对应load]
    search					# 在docker hub 中搜索镜像
    start 					# 启动容器
    stop					# 停止容器
    tag					# 给源中镜像打标签
    top					# 查看容器中运行的进程信息
    unpause					# 取消暂停容器
    version					# 查看docker版本号
    wait					# 截取容器停止时的退出状态值
    

    3. 作业练习

    3.1 部署Nginx

    # 1.搜索镜像 search,可以去docker 搜索,可以看到帮助文档
    # 2.下载镜像 pull
    # 3.运行测试
    docker images 
    
    # -d 后台运行
    # --name 给容器命名
    # -p 宿主机端口,容器内部端口
    docker run -d --name nginx01 -p 3344:80 nginx
    docker ps
    curl localhost:3344
    
    # 进入容器
    docker exec -it nginx01 /bin/bash
    
    docker stop 容器id
    
    
    # 思考问题:我们每次改动nginx配置文件,都需要进入容器内部,十分麻烦,我们可以在容器外部提供一个映射路径,到达在容器外部修改文件,容器内部就可以自动修改   -v 数据卷技术
    

    端口暴露的概念

    3.2 docker来装一个tomcat

    # 官方的使用
    docker run -it --rm tomcat:9.0   # 用完就删除
    
    # 我们之前的启动都是后台,停止容器之后,容器还是可以查看到,docker run -it --rm tomcat:9.0
    
    # 下载再启动
    docker pull tomcat
    
    # 启动运行
    docker run -d -p 3355:8080 --name tomcat101 tomcat
    
    # 测试访问没有问题
    
    # 进入容器
    docker exec -it tomcat101 /bin/bash
    
    # 发现问题:1. linux命令少了  2. 没有webapps
    # 阿里云镜像的原因,默认是最小的镜像,所有不必要的都删除掉,保证最小可运行的环境
      
    思考:在容器外部提供给一个映射路径,webapps,我们在外部防止项目,就自动同步到内部就好了
    

    3.3 部署es+kibana

    # es 暴漏的端口很多
    # es 十分的耗内存
    # es 的数据一般需要放置到安全目录
    # --net somenetwork? 网络配置
    
    # 启动es
    docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:7.6.2
    
    # 启动了linux 就卡住了,docker stats 查看CPU的状态
    # es 十分消耗内存
    
    # 修改配置文件 -e环境配置修改
    docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="Xms64m -Xmx512m" elasticsearch:7.6.2
    
    curl localhost:9200
    

    使用kibana连接es,思考网络如何才能连接过去

    4.Portainer可视化面板

    • portainer(先用这个)
    docker run -d -p 8080:9000 
    --restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer
    
    • Rancher(CI/CD再用)

    什么是portainer?

    • Docker图形化界面管理工具,提供一个后台面板供我们操作
    docker run -d -p 8080:9000 
    --restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer
    

    访问测试:http://ip:8080

    5. Docker镜像讲解

    5.1 镜像是什么

    镜像是一种轻量级、可执行的独立软件保,用来打包软件运行环境和基于运行环境开发的软件,他包含运行某个软

    件所需的所有内容,包括代码、运行时库、环境变量和配置文件

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

    5.1.1如何得到镜像:

    • 远程仓库下载
    • 其他人拷贝给你
    • 自己制作一个镜像dockerfile

    5.2 docker镜像加载原理

    5.2.1 UnionFS(联合文件系统)

    UnionFs(联合文件系统):Union文件系统(UnionFs)是一种分层、轻量级并且高性能的文件系统,他支持对

    文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下( unite

    several directories into a single virtual filesystem)。Union文件系统是 Docker镜像的基础。镜像可以通过分层

    来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像

    特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起

    来,这样最终的文件系统会包含所有底层的文件和目录

    5.2.2 docker镜像加载原理

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

    boots(boot file system

    主要包含 bootloader和 Kernel, bootloader主要是引导加 kernel, Linux刚启动时会加bootfs文件系统,在 Docker镜像的最底层是 boots。

    这一层与我们典型的Linux/Unix系统是一样的,包含boot加载器和内核。

    当boot加载完成之后整个内核就都在内存中了,此时内存的使用权已由 bootfs转交给内核,此时系统也会卸载bootfs。

    rootfs(root file system) 在 bootfs之上。

    包含的就是典型 Linux系统中的/dev,/proc,/bin,/etc等标准目录和文件。

    rootfs就是各种不同的操作系统发行版,比如 Ubuntu, Centos等等。

    对于个精简的OS,rootfs可以很小,只需要包合最基本的命令,工具和程序库就可以了,因为底层直接用Host的kernel,自己只需要提供rootfs就可以了

    由此可见对于不同的Linux发行版, boots基本是一致的, rootfs会有差別,因此不同的发行版可以公用bootfs.

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

    5.2.3 分层理解

    为什么要采用分层结构?

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

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

    查看镜像分层的方式

    docker image inspect
    

    特点

    5.2.4 commit镜像

    docker commit  提交容器成为一个新的副本
    
    # 命令
    docker commit -m="提交的描述信息" -a="作者" 容器id 目标镜像名:[TAG]
    

    实战测试

    # 启动一个默认的tomcat
    
    # 发现这个默认的tomcat是没有webapps应用,镜像的原因,官方的镜像默认 webapps下面是没有文件的
    
    # 手动拷贝进去了基本的文件
    
    # 将修改后的容器通过commit提交为一个新的镜像,我们以后就可以使用修改过的镜像,这就是自己修改过的一个镜像
    

    如果想要保存当前容器的状态,我们可以通过commit来提交,获得一个镜像,类似于虚拟机的快照

    6. 容器数据卷

    6.1 什么是容器数据卷

    docker的理念回顾

    将应用和环境打包成一个镜像

    如果数据都在容器中,那么删除容器,数据就会丢失! 需求:数据可以持久化

    MySQL,容器删了,删库跑路!需求:MySQL数据可以存储在本地

    容器之间可以有一个数据共享的技术!Docker容器中产生的数据,同步到本地!

    这就是卷技术!!目录的挂载,将我们容器内的目录,挂载到Linux上面

    6.1.1 总结:

    **容器的持久化和同步操作!容器之间也是可以数据共享的** 
    

    6.1.2 使用数据卷

    方式一:直接使用命令来挂载 -v

    docker run -it -v  主机目录:容器内目录
    
    # 测试
    docker run -it -v /home/ceshi:/home centos /bin/bash 
    
    # 启动起来之后,我们可以通过 docker inspect 容器id 来查看元数据
    

    # 再次测试
    1. 停止容器
    2. 在宿主机上修改文件
    3. 再次启动容器
    4. 容器内的数据依旧是同步的
    

    好处:

    我们以后修改只需要在本地修改即可,容器内自动同步!

    6.2 实战:安装MySQL

    6.2.1 思考:MySQL 数据持久化问题

    # 获取镜像
    docker pull mysql:5.7
    
    # 运行容器,数据挂载   # 安装启动mysql,需要配置密码!!!
    # 官方测试:docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag
    
    # 运行容器,数据挂载   # 安装启动mysql,需要配置密码!!!
    -d 后台运行
    -p 端口映射
    -v 卷挂载
    -e 环境配置
    --name 容器名字
    
    docker run -d -p 3310:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7
    
    # 启动成功之后,我们在本地使用sql yog测试连接
    # sqlyog 连接到服务器的3310 --- 3310和容器内的3306映射,这个时候就可以连接上了
    
    # 在本地测试创建一个数据库,查看一下我们映射的路径是否OK
    

    6.2.2 假设我们将容器删除

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

    6.3 具名和匿名挂载

    # 匿名挂载
    -v 容器内路径
    docker run -d -P --name nginx01 -v /etc/nginx nginx
    # 查看所有的volume的情况
    ➜  ~ docker volume ls    
    DRIVER              VOLUME NAME
    local               33ae588fae6d34f511a769948f0d3d123c9d45c442ac7728cb85599c2657e50d        
    # 这里发现,这种就是匿名挂载,我们在 -v只写了容器内的路径,没有写容器外的路径!
    
    # 具名挂载
    ➜  ~ docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx nginx
    ➜  ~ docker volume ls                  
    DRIVER              VOLUME NAME
    local               juming-nginx
    
    # 通过 -v 卷名:容器内路径
    
    # 查看一下这个卷
    docker volume inspect juming-nginx
    
    # 所有的docker容器内的卷,没有指定目录的情况下都是在/var/lib/docker/volumes/xxxx/_data,如果指定了目录,docker volume ls 是查看不到的
    

    我们通过具名挂载可以方便的找到我们的一个卷,大多数情况在使用的是具名挂载

    # 三种挂载: 匿名挂载、具名挂载、指定路径挂载
    -v 容器内路径			#匿名挂载
    -v 卷名:容器内路径		#具名挂载
    -v /宿主机路径:容器内路径 #指定路径挂载 docker volume ls 是查看不到的
    

    6.3.1拓展

    # 通过 -v 容器内路径:ro rw 改变读写权限
    ro #read only 只读
    rw #read write 可读可写
    
    # 一旦设置了容器权限,容器对我们挂载出来的内容就有限定了
    docker run -d -P --name nginx05 -v juming:/etc/nginx:ro nginx
    docker run -d -P --name nginx05 -v juming:/etc/nginx:rw nginx
    
    # ro 只要看到ro就说明这个路径只能通过宿主机来操作,容器内部是无法操作!
    

    6.4初始Dockerfile

    Dockerfile就是用来构建docker镜像的构建文件、命令脚本

    通过这个脚本可以生成镜像,镜像是一层一层的,脚本一个个的命令,每个命令都是一层

    # 创建一个dockerfile文件,名字可以随便 建议Dockerfile
    # 文件中的内容 指令(大写) 参数
    FROM centos
    
    VOLUME ["volume01","volume02"]
    
    CMD echo "----end----"
    CMD /bin/bash
    #这里的每个命令,就是镜像的一层!
    
    docker build -f /dockerfile -t kuangshen/centos:v1.0 .
    
    # 启动容器
    

    这个卷和外部有一个同步的目录

    查看一下挂载的路径

    测试一下刚才的文件是否同步

    这种方式之后使用的很多,因为 通常我们会构建自己的镜像

    假设构建镜像的时候没有挂载卷,要手动镜像挂载 -v 卷名:容器内路径

    6.5 数据卷容器

    多个mysql同步数据

    # 启动三个容器,通过我们自己写的容器
    docker run -it --name docker01 kuangshen/centos:1.0
    

    # 此时删除容器docker01,docker02和docker03依旧可以访问这个文件
    拷贝的概念
    

    多个mysql实现数据共享

    docker run -d -p 3306:3306 -v /etc/mysql/conf.d  -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7
    
    docker run -d -p 3307:3306 -e MYSQL_ROOT_PASSWORD=123456 --name mysql02 --volumes-from mysql01  mysql:5.7
    # 这个时候,可以实现两个容器数据同步!
    

    结论

    • 容器之间配置信息的传递,数据卷容器的生命周期一直持续到没有容器使用为止

    • 但是一旦持久化到了本地,这个时候本地的数据是不会删除的

    7. DockerFile

    dockerfile是用来构建docker镜像的文件,命令参数脚本

    7.1 构建步骤

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

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

    7.2 Dockerfile构建过程

    7.2.1 基础知识:

    1. 每个保留关键字(指令)都必须是大写字母
    2. 从上到下顺序执行
    3. 表示注释(#)
    4. 每个指令都会创建提交一个新的镜像,并提交

    Dockerfile是面向开发的,以后发布项目,做镜像,就需要编写dockerfile文件

    Docker镜像逐渐成为企业交付的标准

    Dockerfile:构建文件,定义了一切的步骤,源代码

    Dockerimages:通告Dockerfile构建生成的镜像,最终发布运行的产品

    Docker容器:容器就是镜像运行起来提供服务

    7.3 Dockerfile指令

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

    7.4 实战测试

    Docker Hub中99%镜像都是从这个基础镜像过来的 FROM scratch,然后配置需要的软件和配置来进行构建

    7.4.1 创建一个自己的centos

    # 1.编写Dcokerfile文件
    vim mydockerfile-centos
    
    FROM centos
    MAINTAINER z<419@qq.com>
    
    ENV MYPATH /usr/loacl
    WORKDIR $MYPATH
    
    RUN yum -y install vim
    RUN yum -y install net-tools
    
    EXPOSE 80
    
    CMD echo $MYPATH
    CMD echo "----end----"
    CMD /bin/bash
    
    # 2.通过这个文件构建镜像
    # 命令:docker build -f dockerfile文件路径 -t 镜像名:[tag] .
    docker build -f mydockerfile-centos -t mycentos:0.1 .
    
    # 3.测试运行
    

    我们可以通过 docker history+镜像id 列出本地镜像的变更历史

    我们平时拿到一个镜像,可以研究一下他是怎么做到的

    7.4.2 CMD和ENTRYPOINT的区别

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

    测试CMD

    # 编写dockerfile文件
    vi dockerfile-cmd-test
    FROM centos
    CMD ["ls","-a"]
    
    # 构建镜像
    docker build -f dockerfile-cmd-test -t cmdtest .
    
    # RUN运行,发现我们的ls -a命令生效
    docker run dd8e4401d72f
    
    # 想追加一个命令 -l,成为ls -al
    docker run dd8e4401d72f -l
    
    docker: Error response from daemon: OCI runtime create failed: container_linux.go:349: starting container process caused "exec: "-l":
     executable file not found in $PATH": unknown.
    ERRO[0000] error waiting for container: context canceled 
    # cmd的情况下 -l 替换了CMD["ls","-l"]。 -l  不是命令所有报错
    

    测试ENTRYPOINT

    # 编写dockerfile文件
    $ vim dockerfile-cmd-entrypoint
    FROM centos
    ENTRYPOINT ["ls","-a"]
    
    $ docker build -f dockerfile-cmd-entrypoint -t entrypoint-test .
    
    $ docker run 3c4c9621ed91   
    .
    ..
    .dockerenv
    bin
    dev
    etc
    home
    lib
    lib64
    lost+found ...
    
    # 我们的命令,是直接拼接在我们得ENTRYPOINT命令后面的
    $ docker run entrypoint-test:0.1 -l
    total 56
    drwxr-xr-x   1 root root 4096 May 16 06:32 .
    drwxr-xr-x   1 root root 4096 May 16 06:32 ..
    -rwxr-xr-x   1 root root    0 May 16 06:32 .dockerenv
    lrwxrwxrwx   1 root root    7 May 11  2019 bin -> usr/bin
    drwxr-xr-x   5 root root  340 May 16 06:32 dev
    drwxr-xr-x   1 root root 4096 May 16 06:32 etc
    drwxr-xr-x   2 root root 4096 May 11  2019 home
    lrwxrwxrwx   1 root root    7 May 11  2019 lib -> usr/lib
    lrwxrwxrwx   1 root root    9 May 11  2019 lib64 -> usr/lib64 ....
    

    7.5 实战测试:Tomcat镜像

    1. 准备镜像文件 tomcat 压缩包,jdk的压缩包
    2. 编写dockerfile文件,官方命名Dockerfile,build会自动寻找这个文件,不需要再-f指定
    
    FROM centos 
    MAINTAINER chao      # 名字
    
    COPY readme.txt /usr/local/readme.txt #复制文件
    
    ADD jdk-8u231-linux-x64.tar.gz /usr/local/ #复制解压
    ADD apache-tomcat-9.0.35.tar.gz /usr/local/ #复制解压
    
    RUN yum -y install vim
    
    ENV MYPATH /usr/local #设置环境变量
    WORKDIR $MYPATH #设置工作目录
    
    ENV JAVA_HOME /usr/local/jdk1.8.0_11 #设置环境变量
    ENV CLASSPATH $JAVA_HOME/bin/dt.jar:$JAVA_HOME/lib/tools.jar #设置环境变量 分隔符是:
    ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.35 #设置环境变量
    ENV CATALINA_BASH /usr/local/apache-tomcat-9.0.35 #设置环境变量
    ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin
    
    EXPOSE 8080 #设置暴露的端口
    CMD /usr/local/apache-tomcat-9.0.35/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.35/bin/logs/catalina.out # 设置默认命令
    
    3. 构建镜像
    docker build -t diytomcat .
    
    4. 运行
    $ docker run -d -p 9090:8080 --name kuangshentomcat -v /home/kuangshen/build/tomcat/test:/usr/local/apache-tomcat-9.0.35/webapps/test -v /home/kuangshen/build/tomcat/tomcatlogs/:/usr/local/apache-tomcat-9.0.35/logs diytomcat
    
    5、访问测试
    
    6、发布项目(由于做了卷挂载,我们直接在本地编写项目就可以发布了!)
    
    1. 发布项目
    vi web.xml 
    
      <?xml version="1.0" encoding="UTF-8"?>
      <web-app xmlns="http://java.sun.com/xml/ns/javaee"
               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
                                   http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
               version="2.5">
    
      </web-app>
    
    vi index.jsp
    
    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <title>JC</title>
    </head>
    <body>
    Hello World!<br/>
    <%
    sysem.out.println("---my test web logs---")
    %>
    </body>
    </html>
    

    7.6 发布镜像

    提交的时候也是按照镜像的层级来进行提交的

    7.6.1 DcokerHub

    1. https://hub.docker.com 注册自己的账号
    2. 确定这个账号可以登录
    3. 在我们服务器上提交自己的镜像
    4. 登录完毕之后就可以提交镜像了,docker push
    $ docker login --help
    Usage:  docker login [OPTIONS] [SERVER]
    
    Log in to a Docker registry.
    If no server is specified, the default is defined by the daemon.
    
    Options:
      -p, --password string   Password
          --password-stdin    Take the password from stdin
      -u, --username string   Username
    
    # 登录
    dokcer login -u 用户名
    
    # 上传镜像
    docker push 镜像名
    
    # push镜像的问题
     会发现push不上去,因为如果没有前缀的话默认是push到 官方的library
    # 解决方法
    1. 第一种 build的时候添加你的dockerhub用户名,然后在push就可以放到自己的仓库了
    $ docker build -t chengcoder/mytomcat:0.1 .
    
    2. 第二种 使用docker tag 然后再次push
    $ docker tag 镜像id chengcoder/mytomcat:1.0 #然后再次push
    

    7.6.2 阿里云

    1. 登录阿里云
    2. 找到容器镜像服务
    3. 创建命名空间

    1. 创建容器镜像

    1. 浏览阿里云

    阿里云容器镜像的就参考官方地址

    7.7 docker流程小结

    8. Docker网络

    8.1 理解Docker0

    三个网络

    # 问题:docker 是如何处理容器网络访问的
    

    # 测试  运行一个tomcat
    docker run -d -P --name tomcat01 tomcat
    
    # 查看容器的内部的网络地址   ip addr                               
    
           
    docker exec -it 容器id ip addr
    
    # 查看容器内部网络地址 发现容器启动的时候会得到一个 eth0@if551 ip地址,docker分配!
    550: eth0@if551: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
        link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
           valid_lft forever preferred_lft forever
           
    # 思考? linux能不能ping通容器内部! 可以 容器内部可以ping通外界吗? 可以!
    $ ping 172.17.0.2
    PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
    64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.069 ms
    64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.074 ms
    

    8.1.1 原理

    • 我们每启动一个docker容器,docker就会给docker容器分配一个ip ,我们只要安装了docker,就会有一个网卡docker0 桥接模式,使用的技术是 evth-pair技术
    1. 再次测试ip addr

    1. 再启动一个容器测试,发现又多了一对网卡

    # 我们发现这个容器带来的网卡,都是一对一对出现的
    # evth-pair 就是一对的虚拟设备接口,都是成对出现的,一段连着协议,一段彼此相连
    # 正因为有这个特性,evth-pair 充当一个桥梁,连接各种虚拟网络设备的
    # Openstack,Docker容器之间的连接,OVS的连接,都是使用evth-pair技术
    
    1. 我们测试 tomcat01 和 tomcat02 可以ping通
    docker exec -it tomcat02 ping 172.18.0.2
    
    # 结论:容器和容器之间是可以相互ping通的
    

    结论: tomcat01 和 tomcat02 是共用的一个 docker0

    所有的容器不指定网络的情况下,都是通过docker0通信的,docker会给我们的容器分配一个默认的可用IP

    8.1.2 小结

    • Docker使用的是Linux的桥接,宿主机中是一个Dokcer容器的网桥 docker0

    • Dcoker中的所有的网络接口都是虚拟的,虚拟的转发效率高

    • 只要容器删除,对应网桥一对就都没了

    场景:编写了一个微服务,项目不重启,数据库 IP 换掉了,如何用名字来进行访问容器

    $ docker exec -it tomcat02 ping tomca01   # ping不通
    ping: tomca01: Name or service not known
    # 如何解决?
    通过 --link 解决了网络连通问题
    
    
    # 运行一个tomcat03 --link tomcat02 
    $ docker run -d -P --name tomcat03 --link tomcat02 tomcat
    5f9331566980a9e92bc54681caaac14e9fc993f14ad13d98534026c08c0a9aef
    
    # 用tomcat03 ping tomcat02 可以ping通
    $ docker exec -it tomcat03 ping tomcat02
    PING tomcat02 (172.17.0.3) 56(84) bytes of data.
    64 bytes from tomcat02 (172.17.0.3): icmp_seq=1 ttl=64 time=0.115 ms
    64 bytes from tomcat02 (172.17.0.3): icmp_seq=2 ttl=64 time=0.080 ms
    
    # 用tomcat02 ping tomcat03 ping不通
    
    
    

    探究:inspect

    # 查看hosts 配置
    

    • --link 就是在我们hosts配置中增加了一个 172.18.0.3 tomcat02 312857784cd4

    • 现在已经不建议使用 --link 了

    docker0的问题:不支持容器名连接网络

    8.3 自定义网络

    查看所有的docker 网络

    网络模式:

    1. bridge:桥接(默认)

        	2.	none:不配置网络
                  	3.	host:和宿主机共享网络
                            	4.	container:容器网络互通(用的少,局限大)
      

    测试:

    # 我们直接启动的命令默认有--net bridge,而这个就是我们的docker0
    docker run -d -P --name tomcat01 tomcat
    等价于---> docker run -d -P --name tomcat01 --net bridge tomcat
    
    # docker0 特点:默认bridge,域名不能访问,  --link可以打通连接,但不推荐使用
    
    # 我们可以自定义一个网络
    

    自定义一个网络

    # --driver  bridge
    # --subnet 192.168.0.0/16
    # --gateway 192.168.0.1
    docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
    
    docker network ls
    
    # 我们的网络就创建好了
    docker network inspect mynet
    
    # 测试
    docker run -d -P --name tomcat-net-01 --network mynet tomcat
    docker run -d -P --name tomcat-net-02 --network mynet tomcat
    
    
    # 自定义的网络可以直接ping 通, 不需要使用 --link
    

    • 自定义的网络 docker都已经帮我们维护好了对应的关系,推荐我们平时这样使用网络

    好处:

    redis:不同的集群使用不同 的网络,保证集群是安全和健康的

    mysql:不同的集群使用不同的网络,保证集群是安全和健康的

    8.4 网络连通

    # 测试打通 tomcat01 - mynet
    docker network connect mynet tomcat01
    
    # 连通之后就是将 tomcat01 放到了 mynet 网络下
    
    # 一个容器两个ip地址
    

    • 结论:假设要跨网络操作别人,就需要使用docker network connect 连通

    8.5 实战:部署Redis集群

    # 创建网卡
    docker network create redis --subnet 172.38.0.0/16
    # 通过脚本创建六个redis配置
    for port in $(seq 1 6);
    do 
    mkdir -p /mydata/redis/node-${port}/conf
    touch /mydata/redis/node-${port}/conf/redis.conf
    cat << EOF >> /mydata/redis/node-${port}/conf/redis.conf
    port 6379
    bind 0.0.0.0
    cluster-enabled yes
    cluster-config-file nodes.conf
    cluster-node-timeout 5000
    cluster-announce-ip 172.38.0.1${port}
    cluster-announce-port 6379
    cluster-announce-bus-port 16379
    appendonly yes
    EOF
    done
    
    # 通过脚本运行六个redis
    for port in $(seq 1 6);
    docker run -p 637${port}:6379 -p 1667${port}:16379 --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.38.0.1${port} redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
    
    
    docker exec -it redis-1 /bin/sh #redis默认没有bash
    
    # 创建集群
    redis-cli --cluster create 172.38.0.11:6379 172.38.0.12:6379 172.38.0.13:6379 172.38.0.14:6379 172.38.0.15:6379 172.38.0.16:6379  --cluster-replicas 1
    
  • 相关阅读:
    解决listview在添加项闪烁的问题
    对于水晶报表,我欲哭无泪
    遗憾4年的.net学习和工作
    (转)字符编码笔记:ASCII,Unicode和UTF8
    关于将桌面扩展到监视器的问题 extended my windows desktop onto this monitor
    在win下mb_convert_encoding未定义的问题最终解决方案
    插入数据后, 获取该记录id的方法
    Failed to generate a user instance of SQL Server due to a failure in starting the process for the user instance. The connection will be closed.
    感冒怎么办,少听音乐防止感冒 生活至上,美容至尚!
    2招按摩轻松解除黑眼圈 生活至上,美容至尚!
  • 原文地址:https://www.cnblogs.com/j-chao/p/13212436.html
Copyright © 2011-2022 走看看