docker

一、docker简介

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

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

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


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


2、是什么?

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

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:

  • 官网文档:https://docs.docker.com/engine/install/centos/
  • 安装gcc相关:yum install -y gccyum install -y gcc-c++,安装完执行gcc -v有版本信息就安装成功。
  • 卸载旧版本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

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

  • 登陆阿里云开发者平台:https://dev.aliyun.com/search.html
  • 创建镜像仓库
创建镜像仓库
  • 将本地镜像推送到阿里云:
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)