一、docker简介 1、为什么会出现docker? 一般情况下是开发人员开发好代码,本地测试通过后,打成jar包或者war包,交给运维人员,部署到服务器上。就是这么个过程,经常会出现如下场景:
一样的代码,本地可以跑,服务器上就不行,那这就是环境的问题和配置的问题了。而且,一个产品从开发到上线,往往有开发环境,测试环境,仿真环境和生产环境,每个环境我们都需要安装一遍mysql、redis、nginx,activemq等,运维的工作量也挺大,而且都是重复的工作。为了解决这些痛点,docker就出现了。
2、是什么?
docker就是一个容器,一次构建,处处运行。也就是说,我开发环境安装了mysql、redis,我可以直接将这两个镜像搬到测试环境,开箱即用,而不用重新去配置。
3、虚拟机技术和容器技术:
虚拟机:相当于一台电脑,模拟了一整套完整的操作系统。缺点是启动慢,冗余步骤多,占用资源多。 容器技术(docker):不是模拟完整的操作系统,而是对进程进行隔离,对可以公用的不进行模拟。因此系统变得轻量,启动也是秒级的。 4、docker的核心概念:
容器:就是docker的logo鲸鱼背上那一个个地集装箱。一个集装箱就是一个容器,比如你在docker上要安装redis、mysql、jdk,那么就需要三个集装箱,也就是三个容器。
仓库:存放镜像的地方。有个叫docker hub的网站,它就是仓库。不过国内访问docker hub特别慢,国内一般用阿里云和网易云的仓库。
二、docker的安装 1、安装前提:
如果是centos 6.5,要求系统64位,内核版本2.6.32-431或更高 如果是centos 7,要求系统64,内核版本3.10或者更高 查看系统版本命令:cat /etc/redhat-release
2、docker的安装:
centos 6安装docker:
yum install -y epel-release
安装后的配置文件:/etc/sysconfig/docker
启动docker服务:service docker start
验证版本信息:docker version
,出现版本信息说明安装成功。 centos 7安装docker:
官网文档:https://docs./engine/install/centos/ 安装gcc相关:yum install -y gcc
,yum install -y gcc-c++
,安装完执行gcc -v
有版本信息就安装成功。 yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
安装需要的软件包:yum install -y yum-utils
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常用命令 1、帮助命令:
查看帮助命令:docker --help
,类似linux的man
命令 2、镜像命令: 回顾一下docker的logo,海上有一头鲸鱼,鲸鱼背上有一个个的集装箱。对应关系如下:
常用镜像命令如下:
列出全部镜像(包括中间镜像):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
一起使用 列出运行的容器可选参数有:-a
:列出当前运行和历史上运行过的容器;-l
:显示最近创建的容器;-n
:显示最近创建的n个容器;-q
:静默模式,只显示容器编号;--no-trunc
:显示完整摘要信息 退出容器:exit
:容器停止退出;ctrl + p + q
:容器不停止退出 重启容器:docker restart centos
强制停止容器:docker kill 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
给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
目录,新建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、构建的三个步骤:
登陆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类。所以镜像的基础镜像,即源镜像。 3、dockerfile内容基础知识:
保留字(就是上面那些FROM、ADD等关键字)都必须为大写字母并且后面要跟随至少一个参数 4、dockerfile的执行流程:
执行类似docker commit的操作提交一个新的镜像层 执行dockerfile中的下一条指令直到所有指令都执行完成 5、dockerfile的保留字:
WORKDIR:指定在创建容器后,终端默认登陆进来的工作目录 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。执行docker build -f /mydocker/dockerfile3 -t myip .
进行构建。然后运行该容器,就可以打印出ip信息。如果过执行的时候想加参数,比如docker run -it myip -i
,实际上就是想执行curl的时候加上-i
参数,打印请求头信息,那么抱歉,-i
会覆盖之前的命令,即覆盖CMD ["curl","-s","http://"]
这一样,然后-i
根本就不是一个可执行命令,所以执行报错。要实现上面的需求,即加个-i
,让它真正执行的是curl -s -i https://
,只需要把CMD
换成ENTRYPOINT
,然后启动容器时用docker run -it myip -i
即可。
案例4:ONBUILD
的使用:修改dockerfile3,在后面加上如下的命令: 然后,新建dockerfile4,FROM myip,build的时候会打印出 "我被触发了" 这一句话。
案例5:COPY
和ADD
的使用。首先在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
2、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:镜像版本号