Docker的常用命令
帮助命令
service docker start #先启动 docker
docker # 查看docker的全部命令
docker version # 显示docker的版本信息
docker info # 显示docker的各种信息
docker 命令 --help # 帮助命令
官方的帮助文档和地址https://docs.docker.com/engine/reference/builder/
镜像命令
docker images #查看所有本地的主机上的镜像
测试eg:
[root@yangzihao ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
mysql 5.7 1b12f2e9257b 7 days ago 448MB
#解释
REPOSITORY 镜像的仓库源(镜像的名称)
TAG 镜像的版本
IMAGE ID 镜像的ID
CREATED 镜像的创建时间
SIZE 镜像的大小
#可选项
-a 表示展示本地所有的镜像
-q 表示只展示镜像的id
docker search 镜像 #从docker Hub仓库查询指定的镜像
测试eg:
[root@yangzihao /]# docker search mysql #查询mysql的镜像
NAME DESCRIPTION STARS
mysql MySQL is a widely used, open-source relation… 10120
docker pull 镜像:版本 #下载指定镜像版本 如果不指定版本的话都默认使用最新版
[root@yangzihao /]# docker pull mysql:5.7
#下载完mysql.5.7 再下载最新版试试
[root@yangzihao /]# docker pull mysql
Using default tag: latest #自动使用了最新的版本
latest: Pulling from library/mysql
bb79b6b2107f: Already exists #分层下载
49e22f6fb9f7: Already exists #联合文件系统
842b1255668c: Already exists #(就是在5.7版本中已经存在的东西就不会再下载,而是共用这个文件)
9f48d1f43000: Already exists
c693f0615bce: Already exists
8a621b9dbed2: Already exists
0807d32aef13: Already exists
a56aca0feb17: Pull complete #下载5.7中没有的文件即可 极大的节省了内存
de9d45fd0f07: Pull complete
1d68a49161cc: Pull complete
d16d318b774e: Pull complete
49e112c55976: Pull complete
Digest: sha256:8c17271df53ee3b843d6e16d46cff13f22c9c04d6982eb15a9a47bd5c9ac7e2d
Status: Downloaded newer image for mysql:latest
docker.io/library/mysql:latest
docker rmi -f 镜像ID(容器ID) #删除指定的镜像
[root@yangzihao /]# docker rmi 镜像id
[root@yangzihao /]# docker rmi 镜像id,镜像id,镜像id #删除多个镜像
[root@yangzihao /]# docker rmi -f $(docker images -aq) 删除全部容器
容器命令
说明 : 我们有了镜像才能可以创建容器,Linux ,下载一个centos镜像来测试学习
[root@yangzihao /]# docker pull centos
新建容器并启动 docker run [可选参数] image
docker run [可选参数] image(镜像)
#参数说明
--name "NAME" 容器的名称 eg: tomcat01 tomcat02,用来区分容器
-d 后台的方式运行
-it 使用交互方式运行,进入容器查看内容
-P 随机指定端口
-p 指定容器的端口 -p 8080:8080
-p ip:主机端口:容器端口
-p 主机端口:容器端口 (常用) 主机端口和容器端口进行一个映射
-p 容器端口
#测试,启动并进入容器
[root@yangzihao /]# docker run -it centos /bin/bash
[root@aec187cbb72a /]# ls #查看容器内的centos
bin etc lib lost+found mnt proc run srv tmp var
dev home lib64 media opt root sbin sys usr
#从容器中退回主机
[root@aec187cbb72a /]# exit #容器停止并退出
exit
[root@yangzihao /]# ls
bin dev home lib64 media opt root sbin sys usr
boot etc lib lost+found mnt proc run srv tmp var
列出所有正在运行的容器
docker ps
docker ps [可选参数]
#可选参数
#不写参数 列出当前正在运行的容器
-a #列出当前正在运行的容器+带出历史运行过的容器
-n=? #显示最近创建的容器
-q #只显示容器容器的编号
退出容器
exit #容器直接停止并退出
Ctrl + p +q #容器不停止 只是单纯的回到主机
删除容器
docker rm 容器id #删除指定的容器,不能删除正在运行的容器 如果强制删除 rm -f
docker rm -f $(docker ps -aq) #强制删除所有容器
启动和停止容器的操作
docker start 容器id #启动容器 (容器启动后镜像又重新跑起来了)
docker restart 容器id #重启容器
docker stop 容器id #停止当前正在运行的容器
docker kill 容器id #强制停止当前容器 (如果stop不成功就直接使用kull杀掉容器)
其他常用命令
后台启动容器
#命令 docker run -d 镜像名;
[root@yangzihao /]# docker ps -a
#问题 docker ps 发现 centos 停止了
#常见的坑 :如果docker 容器使用后台运行,那么必须要有一个前台进程,docker没有发现应用 就自动停止
查看日志
docker logs 容器id
#显示日志
-tf #显示日志
--tail number #指定显示日志的条数
查看容器中进程信息ps
docker top 容器id
#测试eg:
[root@yangzihao /]# docker top aa1fc9bfeb30
UID PID PPID C STIME TTY TIME CMD
root 5773 5742 0 13:35 pts/0 00:00:00 /bin/bash
查看容器的数据
docker insepct 容器id
#测试
[root@yangzihao /]# docker inspect aa1fc9bfeb30
进入当前正在运行的容器
方式一:
#我们通常容器都是使用后台方式运行的 ,需要进入容器 修改一些配置
命令
docker exec -it 容器id bashShell
#测试 从主机从新进入了容器
[root@yangzihao /]# docker exec -it aa1fc9bfeb30 /bin/bash
[root@aa1fc9bfeb30 /]#
方式二:
命令
docker attach 容器id
#测试
[root@yangzihao /]# docker attach aa1fc9bfeb30
[root@aa1fc9bfeb30 /]#
区别:
docker exec :进入容器后开启一个新的终端(就是把镜像文件重新开启了) (常用
docker attach: 进入容器后不会重新开启 而是接着之前的状态来
将容器内的文件拷贝到容器外的主机上
docker cp 容器id:容器内路径 目的主机路径
#拷贝是一个手动的过程,未来我们使用 -V 卷的技术,可以实现,自动同步
测试
小结
作业练习
部署nginx
#先搜索 docker search nginx #推荐在docker Hub上搜 可以看到版本信息
#再下载 docker pull nginx
#然后启动镜像 # docker run -d --name nginx01 -p 3344:80 nginx
# -d 后方方式启动
# --name 容器名称
# -p 宿主机端口:容器宽口 容器的端口和服务器的端口映射
测试
思考 :每次改nginx的配置配置文件都要进入容器的内部 ,我要是可以在容器外部提供一个映射路径,达到修改外面的文件,容器的内部就可以自动修改? -v 数组卷!
作业2
#部署tomcat
#下载tomcat
docker pull tomcat:9.0
#运行tomcat
docker run -d --name tomcat01 -p 3355:8080 tomcat:9.0
#进入容器
docker exec -it 69af770952be /bin/bash
#发现问题:1、linux命令变少了 2、webapp下的内容都没了
#原因 :镜像文件的愿意 默认是下载最小的镜像 不必要的文件已经全部剔除掉了
思考:我们以后要部署项目,如果每次都要进入容器是不是十分麻烦?我要是可以在容器外部提供一个映射路径webapps,我们在外部放置项目,就自动同步到内部就好了!
可视化工具
Portainer(中文意思:码头集装箱启动器) 了解一下即可
安装:
docker run -d -p 9000:9000 -v /root/portainer:/data -v /var/run/docker.sock:/var/run/docker.sock --name dev-portainer portainer/portainer
Docker镜像讲解
镜像是什么
镜像是一种轻量级、可执行的独立软件包,它包含运行某个软件所需的所有内容,包括代码运行时、库、环境变量和配置文件
(以后应用,直接打包docker镜像,就可以直接跑起来!!!)
如何得到镜像:
-
从远程仓库下载
-
朋友拷贝给你
-
自己制作一个镜像DockerFile
Docker镜像加载原理
UnionFS(联合文件系统)
UnionFS(联合文件系统):Union文件系统(UnionFS)是一种分层,轻量级并且高性能的文件系统,它支持文件系统修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟机文件系统下。Union文件系统是Docker镜像的基础。镜像可以通过分层来进行继承,基于基础镜(没有父镜像),可以制作各种具体的应用镜像。
特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录
Docker镜像加载原理
docker的镜像实际上由一层一层的文件系统组成,这种层级文件系统UnionFS
bootfs(boot file system)主要包含bootloader和kernel,bootloader主要引导加载kernel,Linux刚启动时就会加载bootfs文件系统,在Docker镜像的最底层是bootfs。这一层与我们典型的Linux/Unix系统是一样的,包含boot加载器和内核。当boot加载完成之后整个内核就都在内存中了,此时内存的使用权已有bootfs转交给内核,此时系统也会卸载bootfs。
rootfs(root file system) , 在bootfs之上。包含的就是典型Linux系统中的/dev,/proc,/bin,/etc 等标准目录和文件。rootfs就是各种不同的操作系统发行版,比如Ubuntu,Centos等等。
平时我们安装进虚拟机的CentOS都是好几个G,为什么Docker这里才200M?
对于一个精简的OS,rootfs可以很小,只需要包含最基本的命令,工具和程序库就可以了,因为底层直接用Host(宿主机)的kernel(内核),自己只需要提供rootfs就可以了。由此可见对于不同的linux发行版,bootfs基本是一致的,rootfs会有差别,因此不同的发型版可以公用bootfs。
分层理解
分层的镜像
我们可以去下载一个镜像,注意观察下载的日志输出,可以看到是一层一层的在下载!
思考:为什么Docker镜像要采用这种分层的结构呢?
最大的好处,我觉得莫过于是资源共享了!比如有多个镜像都从相同的Base镜像构建而来,那么宿主机只需在磁盘上保留一份base镜像,同时内存中也只需要加载一份base镜像,这样就可以为所有的容器服务了,而且镜像的每一层都可以被共享。
查看镜像分层的方式可以通过docker image inspect 命令!
特点
Docker镜像都是只读的,当容器启动时,一个新的可写层被加载到镜像的顶部!
这一层就是我们常说的容器层,容器之下的都叫镜像层
当自己要提交一个镜像文件的时候 会将容器层和镜像层联合起来形成一个新的镜像
如何提交一个自己的镜像
commit镜像
docker commit 提交容器成为一个新的副本(镜像)
docker commit -m "提交的描述信息" -a "作者" 容器id 目标镜像名:版本
实战测试
#启动tomcat
#发现tomcat中 webapps没有文件(官方默认tomcat的webapps下是没有应用的)
#我自己拷贝一些基本文件到webapps下面
#将我们操作过的容器commit,提交为一个镜像,那么我们以后就用这个我们修改过的镜像就可以了
#就好比我们之前学习VM时的快照
到这里 我们就相当于入门了!!!
容器数据卷
什么是容器数据卷
docker的理念回顾
将应用和环境打包成一个镜像 !
问题: 数据?如果数据都存在容器中,那么我们容器删除,数据就会丢失!需求:数据可以持久化
MySQL,容器删了,删库跑路了就!需求:MySQL数据可以存储在本地!
容器之间可以有一个数据共享的技术!Docker容器中产生的数据,同步到本地!
就是卷的技术!目录的挂载,将我们容器内的目录,挂载到Linux上面!!!
总结一句话:容器的持久化和同步操作 !多个容器也可映射同一个目录
使用数据卷
方式一:直接使用命令来挂载 -v
docker run -it -v 主机目录 : 容器目录
#测试
docker run -it -v /home/ceshi:/home centos
#那么主机下面/home/ceshi 和容器内的 /home 进行了一个双向绑定
docker insepect 容器id #接着查看一下容器的信息
说明已经挂载成功了!!!
测试文件的同步
即使容器停止运行了,数据也依然是同步的
实战:安装MySQL
思考:mysql的数据持久化问题???
#下载mysql
[root@yangzihao /]# docker pull mysql:5.7
#启动mysql
-d 后台运行
-p 端口映射
-v 挂载 (可同时挂载多个)volume
--name 容器名称
[root@yangzihao /]# 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=密码 --name mysql01 mysql:5.7
启动成功后用Navicat连接一下
假设我们此时删除容器
发现:我们挂载到本地的数据卷依旧没有丢失,这就实现了容器数据的持久化功能!!!
匿名和具名挂载
匿名挂载
#匿名挂载
-v 容器内的路径
docker run -d -p 3344:80 --name nginx01 -v /etc/nginx nginx
#查看所有的volume的情况
[root@yangzihao ~]# docker volume ls
DRIVER VOLUME NAME
local 5cbf7f114117c4924bb8c69b8d6a65e9e262ca9933fafde1214f774bf7864208
#这里发现,这种就是匿名挂载,我们在-v只写了容器内路径 ,没有写容器外路径
具名挂载
#通过 -v 卷名:容器内路径
docker run -d -p 3344:80 --name nginx02 -v juming-nginx:/etc/nginx nginx
[root@yangzihao /]# docker volume ls
DRIVER VOLUME NAME
local juming-nginx
#查看这个卷
所有的docker容器内的卷,没有指定目录的情况下都是在 /var/lib/docker/volumes/xxxxxxx
我们通过具名挂载可以方便的找到我们的卷,大多数情况下使用具名挂载
#如何确定是具名挂载还是匿名挂载,还是指定路径挂载!!!
-v 容器内路径 #匿名挂载
-v 卷名:容器内路径 #具名挂载
-v /宿主机路径:容器内路径 #指定路径挂载
拓展:
#通过 -v 容器内路径:ro rw 改变读写权限
ro readonly #只读
rw readwrite #可读可写
#一旦这个设置了容器权限,容器对我们挂载出来的内容就有限定了!!!
docker run -d -p 3344:80 nginx02 -v juming-nginx:/etc/nginx:ro nginx
docker run -d -p 3344:80 nginx02 -v juming-nginx:/etc/nginx:rw nginx
#ro 只要看到ro就说明这个路径只能通过宿主机来操作,容器内部是无法操作的。
#如果啥都不指定的话就是默认rw的,可读可写
初识Dockerfile
Dockerfile 就是同来构建docker镜像的构建文件!命令脚本!先体验一下
通过这个脚本可以生成镜像文件,镜像是一层一层的,脚本一个一个的命令,每个命令都是一层!
#创建一个dockerfile文件,名字可以随机 建议就用Dockerfile
#文件中的内容 指令(大写) 参数
FROM centos
VOLUME ["volume01","volume02"]
CMD echo "----end----"
CMD /bin/bash
#启动自己写的容器
这个卷和外部一定有一个同步的目录!!!
我们使用 docker inspect 容器id 查看这个容器的信息 可以看到挂载的信息
数据卷容器
#启动3个容器,通过我们刚才自己写的镜像
#启动第一个镜像
#启动第二个镜像
#启动第三个镜像
以后我们就可以通过 --volume-from实现多个容器间数据的共享
思考 : docker02 和docker03都–volume-from docker01 那么此时把docker01删除了怎么办?
因为他是一种双向拷贝的概念 就是docker02和03已经拷贝了docker01的数据 所以docker01即使删除,docker02和03的数据也都还在
多个mysql实现数据共享
[root@yangzihao /]# docker run -d -p 3306:3306 -v /etc/mysql/conf.d -v /var/lib/mysql -e MYSQL_ROOT_PASSWORD=密码 --name mysql01 mysql:5.7
[root@yangzihao /]# docker run -d -p 3307:3306 -e MYSQL_ROOT_PASSWORD=密码 --name
mysql02 --volume-from mysq01 mysql:5.7
#这个时候 ,可实现两个容器数据同步
结论:
容器之间配置信息的传递,数据卷容器的生命周期一直持续到没有容器使用为止(容器全部被删除)。
但是一旦你持久化到本地,这个时候,本地的数据是不会删除的!
DockerFile
dockerfile 是用来构建docker镜像文件!命令参数脚本!
构建步骤:
1、编写一个dockerfile 文件
2、docker build构建成为一个镜像
3、docker run 运行镜像
4、docker push 发布镜像(DockerHub,阿里云镜像仓库)
很多的官方的镜像都是基础包,很多功能没有,我们通常会自己搭建自己的镜像!!!
官方既然可以制作镜像,那我们也可以!
DockerFile构建过程
基础知识:
1、每个保留关键字(指令)都是必须是大写字母
2、执行从上到下顺序执行
3、#表示注释
4、每个指令都会创建提交一个新的镜像层,并提交!
dockerfile是面向开发的,我们以后要发布项目,做镜像,就需要编写dockerfile文件,这个文件十分简单!
docker镜像逐渐成为企业交付的标准,必须要掌握!!!
步骤:
dockerFile:构建文件,定义了一切的步骤,源代码
dockerImages:通过DockerFile 构建生成的镜像,最终发布和运行产品
docker容器:容器就是镜像运行起来提供服务器
DockerFile的指令
以前的话我们就是使用别人写好的镜像,现在我们知道了这些指令后,我们来练习自己写一个镜像!!!
FROM #基础镜像,一切从这里开始构建
MAINTAINER #镜像是谁写的,姓名<邮箱>
RUN #镜像构建的时候需要运行的命令
ADD #步骤, tomcat镜像,就需要添加tomcat压缩包
WORKDIR #镜像的工作目录
VOLUME #挂载的目录、定义匿名数据卷
EXPOSE #暴露端口配置
CMD #指定这个容器启动的时候要运行的命令,只有最后一个会生效,可被替代(默认命令)
ENTRYPOINT #指定这个容器启动的时候要运行的命令,可追加命令
ONBUILD #当构建一个被继承DockerFile 这个时候就会运行ONBUILD的指令,触发指令
COPY #类似ADD,将我们文件拷贝到镜像中
ENV #构建的时候设置环境变量!
实战测试
Docker Hub中百分之99%镜像都是从这个基础镜像过来的 FROM scratch,然后配置需要的软件和配置 来进行的构建
创建一个自己的centos
#编写
[root@yangzihao dockerfile]# vim mydockfile-centos
[root@yangzihao dockerfile]# cat mydockfile-centos
FROM centos
MAINTAINER yangzihao<[email protected]>
ENV MYPATH /usr/local #ENV来声明变量 就是key-Value 结构
WORKDIR $MYPATH #就是一进这个centos就会默认到达这个目录
RUN yum -y install vim
RUN yum -y install net-tools
EXPOSE 80
CMD echo $MYPATH
CMD echo "--------end-------"
CMD /bin/bash
[root@yangzihao dockerfile]# ls
mydockfile-centos
通过这个dockerfile文件创建镜像
#命令 docker build -f dockerfile文件 -t 镜像名:版本号 .
docker build -f mydockfile-centos -t mycentos:01 .
-f #dockerfile 指定哪个dockerfile文件
-t #target 生成的目标镜像
. #表示在当前目录下
#然后就可以开始运行我们自己创建的centos开始测试了
对比:之前的官方centos
我们增加 之后的镜像
我们可以通过 docker history 命令查看指定镜像的构建过程
我们平时拿到一个镜像,可以研究一下他是怎么做的
CMD 和 ENTRYPOINT区别 了解
CMD #指定这个容器启动的时候要运行的命令,若多个CMD只有最后一个CMD会生效,可被替代
ENTRYPOINT #指定这个容器启动的时候要运行的命令,可追加命令 如果有多个ENTRYPOINT也是只有最后一个生效
测试CMD命令
测试entrypoint
总结:如果发现以后运行镜像 可以在镜像后面追加命令 说明镜像采用的ENTRYPOINT
如果发现只能写完成的原生命令,说明采用的是CMD
一个dockerfile中至多只能有一个CMD,若有多个 只有最后一个会生效
ENTRYPOINT也是文件中如果有多个,只有最后一个会生效
实战Tomcat镜像
1、准备镜像文件 Tomcat 、和jdk压缩包
上传文件到本地服务器
2、编写Dockerfile文件 (这个文件的名字尽量就叫Dockerfile,以后build时会自动找到这个文件)
vim Dockerfile (内容如下)
FROM centos
MAINTAINER yangzihao<[email protected]>
COPY readme.txt /usr/local/readme.txt
ADD jdk-8u161-linux-x64.tar.gz /usr/local/
ADD apache-tomcat-9.0.39.tar.gz /usr/local/
RUN yum -y install vim
ENV MYPATH /usr/local
WORKDIR $MYPATH
ENV JAVA_HOME /usr/local/jdk1.8.0_161
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.39
ENV CATALINA_BASH /usr/local/apache-tomcat-9.0.39
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/bin:$CATALINA_HOME/lib
EXPOSE 8080
CMD /usr/local/apache-tomcat-9.0.39/bin/startup.sh && tail -f /usr/local/apache-tomcat-9.0.39/logs/catalina.out
3 、构建镜像
docker build -t diytomcat .
4、启动镜像
docker run --name yangzihaotomcat -p 9090:8080 -d -v /home/yangzihao/build/tomcat/test:/usr/local/apache-tomcat-9.0.39/webapps/test -v /home/yangzihao/build/tomcat/logs:/usr/local/apache-tomcat-9.0.39/logs diytomcat
5、访问测试
6、项目发布 ( 由于我们挂载了webapps 所以我们直接在本地改就可以同步到容器中的Tomcat中了)
#创建WEB-INF文件夹 mkdir WEB-INF
vim web.xml
<-- 编写xml文件-->
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Application</display-name>
</web-app>
将资源拉进项目文件夹
7、项目访问测试
发现,项目部署成功,可以直接访问ok!
我们以后开发的步骤,需要掌握Dockerfile 的编写! 我们之后的一切都是使用docker镜像来发布运行!
发布自己的镜像
dockerhub
1、地址https://hub.docker.com/choose-plan?ref=signup 先注册账号
2、确定这个账号可以登录
[root@yangzihao download]# docker login -u 帐号 -p 密码
3、我们在服务器上发布自己的镜像 docker push 到dockerhub上
会发现 也是一层一层提交的!!!