docker

作者: 贪挽懒月 | 来源:发表于2020-06-21 15:13 被阅读0次

    一、docker简介

    1、为什么会出现docker?
    一般情况下是开发人员开发好代码,本地测试通过后,打成jar包或者war包,交给运维人员,部署到服务器上。就是这么个过程,经常会出现如下场景:

    • 运维:哥们,你这代码不行啊,跑不起来;
    • 开发:怎么可能,你看我本地是可以的;
    • 运维:你过来看啊,服务器上就是不行;
    • 开发:我的代码怎么可能有问题,你会不会玩?
      ……

    一样的代码,本地可以跑,服务器上就不行,那这就是环境的问题和配置的问题了。而且,一个产品从开发到上线,往往有开发环境,测试环境,仿真环境和生产环境,每个环境我们都需要安装一遍mysql、redis、nginx,activemq等,运维的工作量也挺大,而且都是重复的工作。为了解决这些痛点,docker就出现了。


    欢迎大家关注我的公众号 javawebkf,目前正在慢慢地将简书文章搬到公众号,以后简书和公众号文章将同步更新,且简书上的付费文章在公众号上将免费。


    2、是什么?

    docker就是一个容器,一次构建,处处运行。也就是说,我开发环境安装了mysql、redis,我可以直接将这两个镜像搬到测试环境,开箱即用,而不用重新去配置。

    3、虚拟机技术和容器技术:

    • 虚拟机:相当于一台电脑,模拟了一整套完整的操作系统。缺点是启动慢,冗余步骤多,占用资源多。
    • 容器技术(docker):不是模拟完整的操作系统,而是对进程进行隔离,对可以公用的不进行模拟。因此系统变得轻量,启动也是秒级的。

    4、docker的核心概念:

    • 容器:就是docker的logo鲸鱼背上那一个个地集装箱。一个集装箱就是一个容器,比如你在docker上要安装redis、mysql、jdk,那么就需要三个集装箱,也就是三个容器。

    • 镜像:用来生成容器实例的东西

    • 仓库:存放镜像的地方。有个叫docker hub的网站,它就是仓库。不过国内访问docker hub特别慢,国内一般用阿里云和网易云的仓库。

    二、docker的安装

    1、安装前提:

    • centos 6.5或者更高版本
    • 如果是centos 6.5,要求系统64位,内核版本2.6.32-431或更高
    • 如果是centos 7,要求系统64,内核版本3.10或者更高
    • 查看系统版本命令:cat /etc/redhat-release
    • 查看系统内核版本的命令:uname -r

    2、docker的安装:

    centos 6安装docker:

    • yum install -y epel-release
    • yum install -y docker-io
    • 安装后的配置文件:/etc/sysconfig/docker
    • 启动docker服务:service docker start
    • 验证版本信息:docker version,出现版本信息说明安装成功。

    centos 7安装docker:

    yum remove docker \
               docker-client \
               docker-client-latest \
               docker-common \
               docker-latest \
               docker-latest-logrotate \
               docker-logrotate \
               docker-engine
    
    • 安装需要的软件包:yum install -y yum-utils
    • 设置stable镜像仓库(推荐用阿里云的库):
    yum-config-manager \
       --add-repo \
       http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
    
    • 更新yum软件包索引:yum makecache fast
    • 安装docker ce:yum install -y docker-ce
    • 启动docker:systemctl start docker
    • 测试:docker -v,有版本信息则安装成功,再执行docker run hello-world,会有 hello from docker的信息。
    • 镜像加速配置:
    mkdir -p /etc/docker
    vim /etc/docker/daemon.json
    systemctl daemon-reload
    systemctl restart docker
    

    daemon.json的内容如下:

    # 网易云
    {"registry-mirrors":["http://hub-mirror.c.163.com"]}
    # 阿里云
    {"registry-mirrors":["你阿里云的镜像加速链接"]}
    

    获取阿里云加速镜像链接的方法:
    登陆https://cr.console.aliyun.com,然后点击左下角的“镜像加速器”即可。

    • 卸载:
    systemctl stop docker
    yum -y remove docker-ce
    rm -rf /var/lib/docker
    

    3、hello world:
    上面说过执行docker run hello-world会打印出相关信息,执行这条命令过程如下:

    • 首先会查找本机是否有该镜像
    • 如果有,直接以本机的那个镜像为模板生成容器实例运行
    • 如果没有,去docker hub上查找
    • 找到了,下载到本地,然后生成实例运行,找不到就返回错误信息

    三、docker常用命令

    1、帮助命令:

    • 查看版本信息:docker -v
    • 查看docker信息:docker info
    • 查看帮助命令:docker --help,类似linux的man命令

    2、镜像命令:
    回顾一下docker的logo,海上有一头鲸鱼,鲸鱼背上有一个个的集装箱。对应关系如下:

    • 海 ------ 电脑主机
    • 鲸鱼 ------ docker
    • 集装箱 ------ 容器实例,来自镜像模板

    常用镜像命令如下:

    • 列出主机上的镜像:docker images
    • 列出全部镜像(包括中间镜像):docker images -a
    • 只列出镜像的id:docker images -q
    • 列出全部镜像的id:docker images -qa
    • 显示镜像的摘要信息:docker images --digests
    • 显示完整的镜像信息:docker images --no-trunc
    • 从docker hub上查找xxx镜像:docker search xxx
    • 从docker hub上查找点赞数超过30的xxx镜像:docker search -s 30 xxx
    • 从docker hub上查找xxx镜像,并显示摘要信息:docker search -s 30 --no-trunc xxx
    • 从docker hub上查找能自动构建的xxx镜像:docker search --automated xxx
    • 从docker hub上拉取(下载)最新版的xxx镜像:docker pull xxx
    • 删除xxx(可以是镜像名,也可以是id)镜像:docker rmi xxx
    • 强制删除xxx镜像:docker rmi -f xxx
    • 删除多个镜像:docker rmi -f xxx yyy
    • 删除全部镜像:docker rmi -f $(docker images -qa)

    3、容器命令:
    首先我们执行docker pull centos拉取一个centos的镜像,下面所说的容器都是指centos(都可以是名字或者id)。

    • 新建并启动容器:docker run -it centos
    • 启动容器可选的参数有:--name:为容器指定名字;-d:后台运行容器;-P:随机端口映射;-p:指定端口映射;-i:以交互模式运行容器;-t:为容器重新分配一个伪输入终端,常与-i一起使用
    • 列出当前正在运行的容器:docker ps
    • 列出运行的容器可选参数有:-a:列出当前运行和历史上运行过的容器;-l:显示最近创建的容器;-n:显示最近创建的n个容器;-q:静默模式,只显示容器编号;--no-trunc:显示完整摘要信息
    • 退出容器:exit:容器停止退出;ctrl + p + q:容器不停止退出
    • 启动容器:docker start centos
    • 重启容器:docker restart centos
    • 停止容器:docker stop centos
    • 强制停止容器:docker kill centos
    • 删除容器:docker rm -f centos
    • 一次性删除多个容器:docker rm -f $(docker ps -a -q或者docker ps -a -q | xargs docker rm
    • 后台运行容器:docker run -d centos,启动后,再docker ps,发现根本就没有正在运行的容器,但是刚刚确实启动成功了,因为启动后返回了一个id。这是docker的机制造成的,后台启动docker容器,前台没有交互,docker会认为它没事可做,就杀死了。
    • 查看容器倒数n行日志:docker logs -f -t --tail n 容器id
    • 查看容器内运行的进程:docker top 容器id
    • 查看容器内部细节(返回一个json串):docker inspect 容器id
    • 进入正在运行的容器(ctrl + p + q退出后重新进入):docker attach 容器id
    • 不进入容器但对容器执行相关命令:docker exec -t 容器id 命令;比如不进入docker上运行的centos直接执行ls /命令:docker exec -t centos的id ls /
    • 将容器内的数据拷贝到主机:docker cp 容器id:容器内路径 主机路径

    四、docker镜像

    1、什么是镜像?
    镜像是一种轻量级的可执行的独立软件包。用来打包软件运行环境和基于运行环境开发的软件,包括代码、运行时、库、环境变量和配置文件。docker底层是一个unionFS(联合文件系统),即是一层一层的文件系统组成。

    2、镜像为什么那么大?
    执行docker pull tomcat命令,下载一个tomcat镜像,然后执行docker images,发现一个tomcat就600多兆,为什么那么大?因为刚才说的,镜像是一个联合文件系统,tomcat镜像不仅仅包含tomcat,还包含tomcat运行的各种环境,一个镜像包含了很多层,分层镜像如下:

    tomcat镜像

    3、docker为什么采用分层镜像?
    最大的好处就是共享资源。比如多个镜像都需要jdk,那么宿主机上其实只要保存一份jdk就可以了,内存中也只需要加载一份。镜像的每一层都是可以共享的。

    4、docker commit命令:
    首先我们运行docker run -it -p 8888:8080 tomcat,这里表示docker内部将tomcat运行在8080端口,对外暴露8888端口,即执行完这条命令,我们要用8888端口才能访问到tomcat。如果你访问到的是404,不要方,这是因为你下载的这个版本的tomcat,webapps目录是空的,资源都在webapps-dist目录下,可以执行如下操作:

    • 进入tomcat目录:docker exec -it tomcat容器的id /bin/bash
    • 列出tomcat目录下的文件:ls -l
    • 给webapps重命名:mv webapps webapps2
    • 将webapps-dist改名为webapps:mv webapps.dist webapps

    刷新页面,就可以看到熟悉的tomcat首页了。
    上面是指定对外暴露8888端口,还可以执行docker run -it -P tomcat,大写的P表示随机分配端口,不自己指定。用这个命令启动后,执行docker ps,就可以看到随机分配的端口是什么。

    上面我们对tomcat做了一些修改,把访问会报404的tomcat改成了一个正常的tomcat,我们就可以使用commit命令以我们改好的tomcat为模板,生成一个启动就能直接访问的新的tomcat镜像。执行如下命令:
    docker commit -a="zhusl" -m="normal tomcat" 容器id newtomcat:1.0

    • -a是作者,-m是备注信息,newtomcat是新镜像的名字,1.0是版本号

    五、容器数据卷

    1、是什么?
    我们在docker上运行容器实例,运行时产生的数据,当docker关闭了就没了。但是我们希望有些数据可以持久化保存下来,这个保存的地方的就是容器数据卷,并且保存下来的数据可以共享。

    2、容器数据卷的特点:

    • 数据卷可在容器之间共享或重用数据
    • 卷中的更改可直接生效
    • 数据卷中的更改不会包含在镜像的更新中
    • 数据卷的生命周期一直持续到没有容器使用它为止

    3、添加数据卷的方法:
    添加数据卷有两种方法,一种是命令添加,一种是用dockerfile。
    命令添加:

    • 添加数据卷命令:docker run -it -v /宿主机绝对路径目录:/容器内目录 镜像名
      比如执行docker run -it -v /mydatadir:/dockerdatadir centos,就表示让centos这个镜像和主机之间建立数据卷,主机根目录下的mydatadir和centos镜像根目录下的dockerdatadir目录建立连接,进行数据共享。目录不存会自动新建目录。执行了以上命令后,先查看主机根目录下是否有mydatadir目录,然后再执行docker run -it centos /bin/bash,ls查看一下centos镜像的根目录下是否有dockerdatadir目录。

    • 查看数据卷是否挂载成功:docker inspect 容器id。如果你看到两个目录都成功新建了还是不放心,可以用这条命令查看,如果在返回的内容中看到了如下信息则挂载成功。

      数据卷挂载成功
    • 验证通过数据卷可实现数据共享:首先在主机的mydatadir目录下新建一个test.txt文件,然后发现centos的镜像的dockerdatadir目录也有test.txt文件。然后再centos镜像中往test.txt文件些内容,回到主机再次查看test.txt文件,发现也是有内容的。并且容器推出后,在主机上的mydatadir目录下做的任何操作,在容器重启后,都会被同步到dockerdatadir目录下。

    • 以只读方式添加数据卷:docker run -it -v /宿主机绝对路径目录:/容器内目录:ro 镜像名,加上ro,表示read only,容器只能读数据,不能进行写操作。

    dockerFile添加:

    • 主机根目录下新建mydocker文件夹;
    • 进入mydocker目录,新建dockerfile文件:vim dockerfile,文件内容如下:
    FROM centos
    VOLUME ["/dockerdatadir1","/dockerdatadir2"]
    CMD echo "finished,---------success"
    CMD /bin/bash
    
    • 然后执行build命令生成新的镜像,镜像名叫zhusl/centos:docker build -f /mydocker/dockerfile -t zhusl/centos .
    • 查看镜像:docker images,发现已经有zhusl/centos这个镜像了。这个镜像就是,我们以centos镜像为来源,添加了数据卷,新生成的一个centos。
    • 运行新生成的这个镜像,就可以发现在zhusl/centos的根目录下有两个数据卷,dockerdatadir1和dockerdatadir2。那么这两个数据卷对应宿主机的哪个目录呢?还是执行docker inspect 容器id,就可以看到了,如下图:
      数据卷

    4、数据卷容器:
    上面说了数据卷,数据卷容器其实就是数据卷之间的传递性。比如还是以zhusl/centos镜像为例,先执行docker run -it --name dc01 zhusl/centos,运行一个名为dc01的实例,然后再执行docker run -it --name doc02 --volumes-from dc02 zhusl/centos,以dc01为父容器,运行一个dc02。因为zhusl/centos是添加了数据卷的,所以运行的dc01是挂载了数据卷的,然后dc02又是from dc01,所以dc02也挂载了数据卷。如果还有一个dc03也是继承自dc01,当dc01挂了,dc02和dc03之间也是可以进行数据共享的。

    六、dockerFile

    1、是什么?
    就是一个写命令的文件,然后通过这个文件,就可以构建镜像。

    2、构建的三个步骤:

    • 编写dockerfile文件
    • docker build
    • docker run

    登陆docker hub,然后随便搜索一个镜像,就以centos为例,选择版本然后进入,就可以看到它的dockerfile文件内容。如下就是centos7的dockerfile文件内容:

    FROM scratch
    ADD centos-7-x86_64-docker.tar.xz /
    
    LABEL \
        org.label-schema.schema-version="1.0" \
        org.label-schema.name="CentOS Base Image" \
        org.label-schema.vendor="CentOS" \
        org.label-schema.license="GPLv2" \
        org.label-schema.build-date="20200504" \
        org.opencontainers.image.title="CentOS Base Image" \
        org.opencontainers.image.vendor="CentOS" \
        org.opencontainers.image.licenses="GPL-2.0-only" \
        org.opencontainers.image.created="2020-05-04 00:00:00+01:00"
    
    CMD ["/bin/bash"]
    
    • FROM scratch:相当于java的Object类。所以镜像的基础镜像,即源镜像。
    • ADD:后面的是要添加的东西
    • LABEL:一些标签信息
    • CMD:要执行的命令

    3、dockerfile内容基础知识:

    • 保留字(就是上面那些FROM、ADD等关键字)都必须为大写字母并且后面要跟随至少一个参数
    • 指令从上到下按顺序执行
    • #表示注释
    • 每条指令都会创建一个新的镜像层,并对镜像进行提交

    4、dockerfile的执行流程:

    • docker从基础镜像中运行一个容器
    • 执行一条指令并对容器做出修改
    • 执行类似docker commit的操作提交一个新的镜像层
    • docker再基于刚提交的镜像运行一个新的容器
    • 执行dockerfile中的下一条指令直到所有指令都执行完成

    5、dockerfile的保留字:

    • FROM:表示当前要构建的新镜像是基于哪个镜像的
    • MAINTAINER:作者 + 邮箱
    • RUN:容器构建时需要运行的命令
    • EXPOSE:服务的端口号
    • WORKDIR:指定在创建容器后,终端默认登陆进来的工作目录
    • ENV:设置环境变量用的
    • ADD:要添加进镜像并解压缩的东西
    • COPY:要拷贝进镜像的东西
    • VOLUME:数据容器卷,用于持久化
    • CMD:指定一个容器启动时要运行的命令,一个dockerfile中可以有多个CMD,但最终只有最后一个生效,CMD会被docker run后面的参数替换
    • ENTRYPOINT:指定一个容器启动时要运行的命令,docker run后面的参数不会替换这个,而是在后面追加
    • ONBUILD:触发器。就是另一个镜像基于自己构建时,当另一个镜像启动时自己要做的事

    6、dockerfile构建镜像实操:

    • 案例1:基础命令的使用:就以构建centos为例,我们从docker hub上拉下来的centos,默认路径是/,没有vim编辑器,也没有ifconfig命令。这个centos要实现登陆后默认路径的~,要有vim编辑器,要有ifconfig命令。下面开始编写dockerfile文件:
    # 基于docker hub上拉下来的centos进行构建
    FROM centos
    # 容器启动后工作目录
    WORKDIR ~
    # 安装vim
    RUN yum -y install vim
    # 安装网络工具,使其能用ifconfig命令
    RUN yum -y install net-tools
    # 端口号
    EXPOSE 80
    CMD /bin/bash
    

    新建一个dockerfile2文件,内容就是上面那段,然后执行docker build -f /mydocker/dockerfile2 -t mycentos:1.0 .进行构建。-f后面的是dockerfile2文件的路径,mycentos是镜像名字,1.0是版本号,.代表当前路径。

    执行完后,docker images就会发现有一个新镜像,名字叫mycentos。然后运行该镜像,就会发现这个mycentos可以使用vim和ifconfig的。再回溯一个问题,镜像那么大,是因为它包含了它运行所需的所有环境,那么是不是很浪费空间?就比如这个,我原本有一个centos镜像,只不过没有vim编辑器,现在我构建一个新的有vim的mycentos,docker images 显示centos 600M,mycentos 620M,那这两个是不是就要占用1个G?其实并不是,因为镜像是可以共享的,mycentos 是form centos的,也就是说这600其实是共用的,最后这两个镜像其实占空间就是620M。

    执行docker history 镜像id,就可以列出镜像的历史,即这个镜像有多少层。

    • 案例2:CMD指令的使用:执行docker run -it -p 7777:8080 tomcat ls -l,就是在启动命令后追加ls -l参数,列出登陆后的目录。然后发现tomcat根本就没有启动,只是列出了tomcat的目录。因为dockerfile的CMD命令只有最后一行生效,ls -l这个命令把启动tomcat的CMD覆盖了,所以没启动。

    • 案例3:ENTRYPOINT的使用:新建一个dockerfile3,内容如下:

    FROM centos
    RUN yum install -y curl
    CMD ["curl","-s","http://ip.cn"]
    

    意思就是制作一个镜像,一启动,就可以查出本机的IP。执行docker build -f /mydocker/dockerfile3 -t myip .进行构建。然后运行该容器,就可以打印出ip信息。如果过执行的时候想加参数,比如docker run -it myip -i,实际上就是想执行curl的时候加上-i参数,打印请求头信息,那么抱歉,-i会覆盖之前的命令,即覆盖CMD ["curl","-s","http://ip.cn"]这一样,然后-i根本就不是一个可执行命令,所以执行报错。要实现上面的需求,即加个-i,让它真正执行的是curl -s -i https://ip.cn,只需要把CMD换成ENTRYPOINT,然后启动容器时用docker run -it myip -i即可。

    • 案例4:ONBUILD的使用:修改dockerfile3,在后面加上如下的命令:
    ONBUILD RUN echo "我被触发了"
    

    然后,新建dockerfile4,FROM myip,build的时候会打印出 "我被触发了" 这一句话。

    • 案例5:COPYADD的使用。首先在opt目录下先搞两个tar.gz包和一个copy.txt文件,一个jdk8,一个tomcat9。编写dockerfile,内容如下:
    FROM   centos
    # 复制文件
    COPY copy.txt /usr/local/cincontainer.txt
    # 添加并解压jdk
    ADD jdk-8u171-linux-x64.tar.gz /usr/local
    # 添加并解压tomcat9
    ADD apache-tomcat-9.0.8.tar.gz /usr/local
    # 安装vim
    RUN yum install -y install vim
    # 设置登陆落脚点
    ENV MYPATH /usr/local
    WORKDIR $MYPATH
    # 配置jdk和tomcat环境变量
    ENV JAVA_HOME /usr/local/jdk1.8.0_171
    ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
    ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.8
    ENV CATALINA_BASE /usr/local/apache-tomcat-9.0.8
    ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:CATALINA_HOME/bin
    # 指定容器运行端口
    EXPOSE 8080
    # 启动命令
    CMD /usr/lcoal/apache-tomcat-9.0.8/bin/startup.sh && tail -F /usr/local/apache-tomat-9.0.8/bin/logs/catalina.out
    

    七、常用镜像安装

    1、MySQL:

    • 拉取镜像:docker pull mysql:5.7
    • 启动并添加数据卷:docker run -p 3306:3306 --name mysql -v /zhusl/mysql/conf:/etc/mysql/conf.d -v /zhusl/mysql/logs:/logs -v /zhusl/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7
    • 进入容器:docker exec -it 容器id /bin/bash
    • 使用mysql:mysql -u root -p

    2、redis:

    • 搜索镜像:docker search redis
    • 拉取镜像:docker pull redis
    • 启动redis镜像:docker run -p 6379:6379 -v /zhusl/redis/data:/data -v /zhusl/redis/conf/redis.conf:/usr/local/etc/redis/redis.conf -d redis redis-server /usr/local/etc/redis/redis.conf --appendonly yes
      appendonly yes表示开启aof。
    • 连接redis:docker exec -it redis容器id redis-cli

    八、本地镜像推送到阿里云

    创建镜像仓库
    • 将本地镜像推送到阿里云:
    docker login --username= registry.cn-hangzhou.aliyuncs.com
    # 执行完上一条命令会要你输入用户名和密码
    docker tag 镜像id registry.cn-hangzhou.aliyuncs.com/zhushulin/redis:镜像版本号
    docker push registry.cn-hangzhou.aliyuncs.com/zhushulin/redis:镜像版本号
    

    相关文章

      网友评论

        本文标题:docker

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