在centos7添加docker命令自动补全
yum install -y bash-completion
source /usr/share/bash-completion/bash_completion
source /usr/share/bash-completion/completions/docker
# 重开一个终端,即可使用
镜像
Docker镜像(Image)就是一个只读的模板。镜像可以用来创建Docker容器,一个镜像可以创建多个容器。
容器与镜像的关系类似于面向对象编程中的对象与类
DOCKER | 面向对象 |
---|---|
镜像 | 类 |
容器 | 对象 |
容器
Docker利用容器(Container)独立运行的一个或一组应用。容器是用镜像创建的运行实例。
它可以被启动、开始、停止、删除。每个容器都是相互隔离的、保证安全的平台。
可以把容器看作是一个简易版的Linux环境(包括root用户权限、进程空间、用户空间和网络空间等)和运行在其中的应用程序。
容器的定义和镜像几乎一模一样,也是一堆层的统一视角,唯一区别在于容器的最上面那一层是可读可写的。
DOCKER
Docker本身是一个容器运行载体或称之为管理引擎。我们把应用程序和配置以来打包好形成一个可交付的运行环境,这个打包好的运行环境就是image镜像文件。只有通过这个镜像文件才能生成Docker容器。image文件可以看作是容器的模板。Docker根据image文件生成容器的实例。同一个image文件,可以生成多个同时运行的容器实例。
Docker和虚拟机的比较
Docker | 虚拟机 | |
---|---|---|
操纵系统 | 与宿主机共享OS | 宿主机OS上运行虚拟机OS |
存储大小 | 镜像小,便于存储与传输 | 镜像庞大 |
运行性能 | 几乎无额外性能损失 | 操作系统额外的CPU、内存消耗 |
移植性 | 轻便、灵活 | 笨重,与虚拟机技术耦合度高 |
部署速度 | 快速 | 较慢 |
常用docker命令
镜像命令
docker image pull 是下载镜像的命令。镜像从远程镜像仓库服务的仓库中下载。默认情况下,镜像会从 Docker Hub 的仓库中拉取。
#命令会从 Docker Hub 的 alpine 仓库中拉取标签为 latest 的镜像。
docker image pull alpine:latest
#列出了本地 Docker 主机上存储的镜像。可以通过 --digests 参数来查看镜像的 SHA256 签名。
docker image ls # 等价于 docker images
#命令非常有用!该命令完美展示了镜像的细节,包括镜像层数据和元数据。
docker inspect image
docker inspect busybox 查看busybox镜像的细节
docker image rm -f <镜像名>用于强制删除镜像。
#命令的含义是删除 alpine:latest 镜像。当镜像存在关联的容器,并且容器处于运行(Up)或者停止(Exited)状态时,不允许删除该镜像。
docker image rm alpine:latest
# 查看镜像名
docker search <镜像名>
docker search tomcat --filter=stars=30 查看star超过30的镜像
sudo systemctl restart docker 重启docker
docker info 查看docker的信息
docker version 查看docker的版本
docker dockerhelp
ps -ef | grep docker 查看docker进程
容器命令
注意:容器不仅可以运行tomcat、nginx,还能运行centos、ubuntu等操作系统(简易版,只有几百兆)
-i:以交互模式运行容器,通常与-t同时使用
-t:为容器重新分配一个伪输入终端,通常与-i同时使用
别名 Image id
docker run -it --name mycentos 831691599b88 运行镜像id为831691599b88的系统,并其别名为mycentos
exit 退出容器并关闭容器
docker start mycentos 启动容器
Ctrl+P+Q 退出容器但是容器没有关闭
docker ps 查看当前有哪些容器在运行 选项:-n 3 表示查看3个容器(包括停止的)
#进入容器
docker attach mycentos(别名或是容器id都是可以的)
#在不进入容器中,就直接对容器内进行操作
docker exec -t mycentos ls -l /tmp
#关闭容器 容器别名或是容器id
docker stop mycentos
#删除已经停止的容器(未停止的容器需要先停止再删除)
docker rm mycentos
#删除所有的容器
docker rm -f$(docker ps -a -q)
#后台运行centos容器,注意:docker ps 查不到,这是因为前台没有运行的容器,所以导致后台的容器没事可做,所以自动关闭了
docker run -d centos
#后台运行一个容器,容器内每隔2秒一直打印hello zzyy(这样可以让后台容器不自动关闭)
docker run -d centos /bin/sh -c "while true;do echo hello zzyy; sleep 2; done"
#查看所有的日志
docker logs f576a553e9dc
#容器id
docker logs -f -t --tail 10 f576a553e9dc 查看日志
-t 加入时间戳
-f 跟随最新的日志打印
--tail 数字显示最后多少条
#查看容器内的进程
docker top f576a553e9dc
#查看容器内的细节
docker inspect f576a553e9dc
#docker cp 容器ID:容器内路径 目的主机路径
docker cp 7d0410eb37f1:/usr/local/container.txt /tmp/c.txt
UnionFS 联合文件系统
Union文件系统是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层叠加,同时将不同目录挂载到同一虚拟文件系统下。Union文件系统是Dcoker镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作出各种具体的应用镜像。
特性:一次同时加载多个文件系统,但是从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录。
启动tomcat
# 8888 是宿主机的端口,8080是tomcat的端口,将宿主机的8888映射到tomcat的8080端口
docker run -it -p 8888:8080 tomcat
#浏览器输入 39.99.196.155:8888即可访问,注意:需要在云服务的安全组中添加安全组,将端口号8888添加进去
# docker commit的命令格式
# docker commit -a="作者名" -m="描述信息" 容器ID 要创建的目标镜像名:[标签名]
docker commit -a="zhangyue" -m="解决tomcat无法访问的问题" 2b97e7dab8d8 tomcat8:8.8
无法访问tomcat,解决办法:https://blog.csdn.net/abcde123_123/article/details/103879385
Docker容器数据卷
卷说就是目录或是文件,存在于一个或是多个容器中,由docker挂载到容器中,但不属于联合文件系统,因此能够绕过UFS提供的一些用于持续存储或是共享数据的特性。
卷的设计目的就是数据的持久化,完全独立于容器的生命周期,因此Docker不会在容器删除时删除其挂载的数据卷。
特点:
- 数据卷可在容器之间共享或是重用数据
- 卷中的更改可以直接生效
- 数据卷中的更改不会包含在数据的更新中
- 数据卷的生命周期一直持续到没有容器使用它为止
添加容器卷
方法一 直接命令添加
# docker run -it -v /宿主绝对路径目录:/容器内目录 镜像id
docker run -it -v /myDataVolume:/dataVolumeContainer centos
# 查看数据是否挂载成功
dokcer inspect ca563d029201 # 在详细信息里能看到
验证:
我们在宿主机的myDataVolume文件夹下面新建了一个文本文档,然后在容器的dataVolumeContainer文件夹下发现了同样的文档。
那么容器停止退出之后,主机修改后数据是否同步呢?答案是可以同步的。
带权限的命令,为了防止随意修改容器内的数据
# docker run -it -v /宿主绝对路径目录:/容器内目录:ro 镜像id
# ro 表示容器对于容器内目录的内容只读,无法修改
docker run -it -v /myDataVolume2:/dataVolumeContainer:ro centos
# 容器无法对dataVolumeContainer文件夹下的内容进行修改
方法二 DockerFile添加
步骤一:根目录下新建mydocker文件夹进入
mkdir mydocker
步骤二:在Dockerfile中使用Volume指令来给镜像添加一个或是多个数据卷
#volume 语法规则,注意:Volume 和后面的[]之间存在空格
VOLUME ["/dataVolumeContainer","dataVolumeContainer2"]
步骤三:Dockerfile构建
# 新建Dockerfile文件
vim Dockerfile
Dockerfile文件内容
#依赖镜像
FROM centos
#在镜像centos的根目录下新建两个容器卷dataVolumeContainer1、dataVolumeContainer2
VOLUME ["/dataVolumeContainer1","/dataVolumeContainer2"]
CMD echo "finished, ------success1"
CMD /bin/bash
上面文件内容可以翻译成这样的一条指令
docker run -it -v /host1:/dataVolumeContainer1 -v /host2:/dataVolumeContainer2 centos /bin/bash
注意:该指令无法使用,因为没有迁移性
步骤四:build后生成镜像,获得一个新镜像
# 回到主目录下
# dockerfile文件位置 新镜像的名字 当前目录
docker build -f mydocker/Dockerfile -t zhangyue/centos .
# 查看所有镜像
docker images
步骤五:run容器
# 运行新镜像 新镜像id
docker run -it bdcbd18811bb
# 查看容器卷
ls -l
# 因为我们指定宿主机的位置,所以可以在容器的详细信息中查看
docker inspect 16254d04ea01
# 在详细信息中,有个Mounts的标签,在其下面有两个key,一个是Destination,其内容是容器内容器卷的位置,另一个是Source,其内容就是容器卷在宿主机挂载的位置
如果cannot open directory.: Permission denied
解决办法:在挂载目录后多加一个–privileged=true
数据卷容器
容器间传递共享(–volumes-from)
步骤一:先启动一个父容器dc01,dataVolumeContainer2新增内容
# 找到要运行镜像的id
dcoker images
#运行镜像
# 如果不自己添加一个别名,那么会给容器随机分配一个别名
# 添加别名
docker run -it --name dc01 bdcbd18811bb
# 进入容器,dataVolumeContainer2 文件夹中添加一个文件dc01_add.txt
cd dataVolumeContainer2
touch dc01_add.txt
步骤二:dc02/dc03继承自dc01
# 核心指令 父容器 和dc01一样的镜像
docker run -it --name dc02 --volumes-from dc01 bdcbd18811bb
docker run -it --name dc03 --volumes-from dc01 bdcbd18811bb
进入容器dc02的dataVolumeContainer2文件夹,可以发现dc01_add.txt文件。
此时,在容器dc02的dataVolumeContainer2文件夹添加文件,容器dc01的dataVolumeContainer2也能看到。dc03同理。所以,dc01、dc02、dc03三个容器的dataVolumeContainer2下的内容都能共享。
问题一:如果dc01被删除了,修改dc02后,dc03可以访问吗?
答案:经过实验发现,是可以的。
问题二:新建dc04继承dc03,再删除dc03,那么修改dc02,dc04可以访问吗?
答案:经过实验发现,是可以的。
结论:容器之间配置信息的传递,数据卷的生命周期一直持续到没有容器使用它位为止。
Dockerfile解析
定义:dockerfile是用来构建Docker镜像的构建文件,是一系列命令和参数构成的脚本
构建三步骤:编写dockerfile文件、docker build、docker run
Dockerfile内容基础知识
- 每条保留字指令都必须为大写字母且后面要跟随至少一个参数
- 指令按照从上到下,f顺序执行
- 每条指令都会创建一个新的镜像层,并对镜像进行提交
Dockerfile构建过程解析
Docker执行Dockerfile的大致流程:
- docker从基础镜像运行一个容器
- 执行一条指令并对容器作出修改
- 执行类似docker commit的操作提交一个新的镜像层
- docker再基于刚提交的镜像运行一个新的容器
- 执行dockerfile中的下一条指令直到所有指令都执行完成
从应用软件来看,Dockerfile、Docker镜像和Docker容器分别代表软件的三个不同的阶段
Dockerfile是软件的原材料
Docker镜像是软件的交付品
Docker容器则可以认为是软件的运行态
Dockerfile面向开发,Docker镜像成为交付标准,Docker容器涉及部署和运维,三者缺一不可,合力充当Docker体系的基石。
Dockerfile定义了进程所需要的一切东西。Dockerfile涉及的内容包括执行代码或是文件、环境变量、依赖包、运行时环境、动态链接库、操作系统的发行版、服务进程和内核进程(当应用进程需要和系统服务和内核进程打交道,这时需要考虑如何设计namespace权限控制)
Dockerfile 体系结构
保留字指令
-
FROM
基础镜像,当前新镜像是基于哪个镜像
-
MAINTAINER
镜像维护者的姓名和邮箱地址
-
RUN
容器构建时需要运行的命令
-
EXPOSE
当前容器对外暴露出的端口
-
WORKDIR
指定在创建容器后,终端默认登陆进来的工作目录,一个落脚点
-
ENV
用来在构建镜像过程中设置环境变量
-
ADD
将宿主机目录下的文件拷贝进镜像且ADD命令会自动处理URL和解压tar压缩包
-
COPY
类似于ADD,拷贝文件和目录到镜像中
将从构建上下文目录中<源路径>的文件/目录复制到新的一层的镜像内的<目标路径>位置
-
VOLUME
容器数据卷,用于数据保存和持久化工作
-
CMD
指定一个容器启动时要运行的命令
Dockerfile中可以有多个CMD指令,但只有最后一个生效,CMD会被docker run之后的参数替换
-
ENTRYPOINT
指定一个容器启动时要运行的命令
ENTRYPOINT的目的和CMD一样,都是在指定容器启动程序及参数,但是与CMD不同的是,会追加,不是覆盖
-
ONBUILD
当构建一个被继承的Dockerfile时运行命令,父镜像在被子继承后父镜像的
onbuild
被触发
保留字案例
centos6.8的dockerfile
# 来自scratch镜像,类似于java中的Object类,是所有类的祖先
FROM scratch
#维护者的信息
MAINTAINER The CentOS Project <cloud-ops@centos.org>
ADD c68-docker.tar.xz /
# 标签
LABEL name="CentOS Base Image" \
vendor="CentOS" \
license="GPLv2" \
build-date="2016-06-02"
# 默认登陆位置,json串形式的命令
CMD ["/bin/bash"]
有时候默认的dockerfile达不到我们的需求,所以需要自定义镜像mycentos。
我们的要求:1、修改登陆位置;2、安装vim和net-tools工具;3、暴露80端口
-
编写
在mydocker文件下,新建Dockerfile2文件
vim mydocker/Dockerfile2
Dockerfile2的内容
# 继承本地镜像的centos FROM centos # 作者的个人信息 MAINTAINER zhangyue<zhangyue@163.com> # 设置环境变量 ENV MYPATH /usr/local # 设置登陆位置 WORKDIR $MYPATH # 安装vim RUN yum -y install vim # 安装 net-tools RUN yum -y install net-tools EXPOSE 80 CMD echo $MYPATH CMD echo "success ----------- OK" CMD /bin/bash
-
构建
#1.3是tag, 最后的 . 表示的是当前目录 docker build -f mydocker/Dockerfile2 -t mycentos:1.3 .
-
运行
# 查找新建的镜像 docker images # 运行镜像 docker run -it 721c5301fd4c # 查看docker的历史 docker history 721c5301fd4c
CMD介绍
以tomca举例,tomcat中dockerfile的最后一行是:CMD ["catalina.sh", "run"](这时json串形式的指令,翻译过来就是:catalina.sh run )
,这个意味着最后执行的这条语句。
正常执行tomcat启动指令:docker run -it -p 8888:8080 tomcat
现在对tomcat启动指令进行修改:docker run -it -p 8888:8080 tomcat ls -l
,执行后发现无法启动tomcat,而是打印出ls -l
的效果
这是因为CMD的特性:Dockerfile中可以有多个CMD指令,CMD会被docker run之后的参数替换,所以无法启动。
ENTRYPOINT介绍
docker run之后的参数会被当做参数传递给ENTRYPOINT,之后形成新的命令组合
利用案例进行解释:制作CMD版可以查询IP信息的容器
-
新建Dockerfile3
FROM centos RUN yum install -y curl # 下载百度首页 CMD ["curl", "www.baidu.com"]
-
新建镜像
docker build -f mydocker/Dockerfile3 -t mybaidu .
-
运行
# 查看新建镜像id docker images # 运行新镜像mybaidu docker run -it ff61c72c1c33
返回百度的首页
如果我们想要看http的报文头,那么在linux中的指令就是:curl -i www.baidu.com
。那么在容器运行时添加-i
可以吗?
尝试下:
# 希望可以返回http报文头
docker run -it ff61c72c1c33 -i
# 结果报错
Error response from daemon: oci runtime error: container_linux.go:235: starting container process caused "exec: \"-i\": executable file not found in $PATH".
# 这是因为CMD的特性,在docker指令后添加选项,只会替换之前的CMD命令
# 翻译成在dockerfile中应该是:
CMD ["curl", "www.baidu.com"]
CMD -i
# 如果我们希望添加 -i 这个参数,我们就必须完整的输入这个命令
docker run ff61c72c1c33 curl www.baidu.com -i
那么为了解决这个问题,我们使用ENTRYPOINT保留字
#1.新建Dockerfile4
FROM centos
RUN yum install -y curl
# 下载百度首页
CMD ["curl", "www.baidu.com"]
# 2. 构建和运行
docker build -f mydocker/Dockerfile4 -t mybaidu2 .
# 查看新建镜像id
docker images
# 运行新镜像mybaidu2
docker run mybaidu2
# 实验,在后面添加 -i
docker run mybaidu2 -i
# 结果:返回了http报文头,完美
ONBUILD介绍
当构建一个被继承的Dockerfile时运行命令,父镜像在被子继承后父镜像的onbuild
被触发。
# 1. 写Dockerfile,命令为Dockerfile4,作为父镜像,其内容如下
FROM centos
RUN yum install -y curl
ENTRYPOINT ["curl","www.baidu.com"]
# 当该镜像被继承时,会触发输出 father images onbuild ------------- 886
ONBUILD RUN echo "father images onbuild ------------- 886"
# ------------------------------------------------------------- 分割上下,以免混淆
# 2. 以Dockerfile4构建新的镜像mybaidu_father
docker build -f mydocker/Dockerfile4 -t mybaidu_father .
# 3. 写Dockerfile,命令为Dockerfile5,其内容如下
# 继承父镜像 mybaidu_father
FROM mybaidu_father
RUN yum install -y curl
CMD ["curl", "www.baidu.com"]
# ------------------------------------------------------------- 分割上下,以免混淆
# 4. 以Dockerfile5构建新的镜像mybaidu_son
docker build -f mydocker/Dockerfile5 -t mybaidu_son .
以Dockerfile5构建新的镜像mybaidu_son时,果真在终端打印出:father images onbuild ------------- 886
Dockerfile案例
自定义tomcat9
由于下载不下来jdk-8u171-linux-X64.tar.gz和apache-tomcat-9.0.8.tar.gz,所以这个案例没有做,只看了下dockerfile
FROM centos
MAINTAINER zhangyue<zhangyue@163.com>
# 把宿主机当前上下文的c.txt 拷贝到容器/usr/local/路径下
COPY c.txt /usr/local/cincontainer.txt
# 把java与tomcat添加到容器中
ADD jdk-8u171-linux-X64.tar.gz /usr/local/
ADD apache-tomcat-9.0.8.tar.gz /usr/local/
# 安装vim编辑器
RUN yum -y install vim
# 设置工作访问时候的WORKDIR路径,登陆落脚点
ENV MYPATH /usr/local
WORKDIR $MYPATH
# 配置java和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
#启动时运行 tomcat
# ENTRYPOINT["/usr/local/apache-tomcat-9.. 8/bin/startup. sh
# CMD["/usr/local/apache -tomcat-908/bin/catalina. sh","run
CMD /usr/local/apache-tomcat-908/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.8/bin/logs/catalina.out
Docker安装mysql
# 拉取mysql5.6
docker pull mysql:5.6
# 运行镜像,这是一条指令
docker run -p 12345:3306 --name mysql
# -v 添加数据容器卷
# 将主机/zhangyue/mysql/conf 挂载到/etc/mysql/conf.d 下
-v /zhangyue/mysql/conf:/etc/mysql/conf.d
# 将主机/zhangyue/maysql/logs目录挂载到容器的logs目录
-v /zhangyue/maysql/logs:/logs
# 将主机/zhangyue/mysql/data目录挂载到容器的/var/lib/mysql
-v /zhangyue/mysql/data:/var/lib/mysql
# -e 初始化root用户的密码
-e MYSQL_ROOT_PASSWORD=123456
# -d 后台于运行
-d mysql:5.6
#------------------------------------
# 进入容器
docker exec -it 6f2f1039225d /bin/bash
# 输入密码 123456
mysql -uroot -p
#进入mysq内
show database; #可以看到mysql中的表
# 将容器内数据库的内容备份到宿主机
docker exec 6f2f1039225d sh -c 'exec mysqldump --all-database -uroot -p"123456"' > /zhangyue/all-databases.sql
在本地电脑的mysql客户端设置hostname和端口可以连接到容器mysql,注意这里的端口号是:12345,这是容器暴露给我们,当我们连接容器之后,会映射到3306端口。
Docker安装Redis(不完整)
# 拉取Redis3.2
docker pull redis:3.2
# 运行镜像
docker run -p 6379:6379 -v /zhangyue/myredis/data:/data
-v /zhangyue/myredis/conf/redis.conf:/usr/local/etc/local/redis/redis.conf
-d redis:3.2 redis-server /usr/local/etc/redis/redis.conf
--appendonly yes
# 还需要修改redis.conf,没做,所以redis没有运行起来
将正在运行的容器生成新的镜像
# 运行镜像mycentos:1.3
docker run -it 721c5301fd4c
# 得到正在运行的容器 eb10863daad4,在该容器中新建文本文档c.txt
touch c.txt
# 将容器eb10863daad4提交为镜像mycentos:1.4
docker commit -a zhangyue -m "image with installed vim" eb10863daad4 mycentos:1.4
# 然后运行新的镜像mycentos:1.4,发现该镜像中存在之前新建的文本文档 c.txt
将镜像推送到阿里云以后再补充。。。