Docker基础知识

在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不会在容器删除时删除其挂载的数据卷。

特点:

  1. 数据卷可在容器之间共享或是重用数据
  2. 卷中的更改可以直接生效
  3. 数据卷中的更改不会包含在数据的更新中
  4. 数据卷的生命周期一直持续到没有容器使用它为止
添加容器卷
方法一 直接命令添加
# 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内容基础知识

  1. 每条保留字指令都必须为大写字母且后面要跟随至少一个参数
  2. 指令按照从上到下,f顺序执行
  3. 每条指令都会创建一个新的镜像层,并对镜像进行提交
Dockerfile构建过程解析

Docker执行Dockerfile的大致流程:

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

从应用软件来看,Dockerfile、Docker镜像和Docker容器分别代表软件的三个不同的阶段

Dockerfile是软件的原材料

Docker镜像是软件的交付品

Docker容器则可以认为是软件的运行态

Dockerfile面向开发,Docker镜像成为交付标准,Docker容器涉及部署和运维,三者缺一不可,合力充当Docker体系的基石。

Dockerfile定义了进程所需要的一切东西。Dockerfile涉及的内容包括执行代码或是文件、环境变量、依赖包、运行时环境、动态链接库、操作系统的发行版、服务进程和内核进程(当应用进程需要和系统服务和内核进程打交道,这时需要考虑如何设计namespace权限控制)

Dockerfile 体系结构
保留字指令
  1. FROM

    基础镜像,当前新镜像是基于哪个镜像

  2. MAINTAINER

    镜像维护者的姓名和邮箱地址

  3. RUN

    容器构建时需要运行的命令

  4. EXPOSE

    当前容器对外暴露出的端口

  5. WORKDIR

    指定在创建容器后,终端默认登陆进来的工作目录,一个落脚点

  6. ENV

    用来在构建镜像过程中设置环境变量

  7. ADD

    将宿主机目录下的文件拷贝进镜像且ADD命令会自动处理URL和解压tar压缩包

  8. COPY

    类似于ADD,拷贝文件和目录到镜像中

    将从构建上下文目录中<源路径>的文件/目录复制到新的一层的镜像内的<目标路径>位置

  9. VOLUME

    容器数据卷,用于数据保存和持久化工作

  10. CMD

    指定一个容器启动时要运行的命令

    Dockerfile中可以有多个CMD指令,但只有最后一个生效,CMD会被docker run之后的参数替换

  11. ENTRYPOINT

    指定一个容器启动时要运行的命令

    ENTRYPOINT的目的和CMD一样,都是在指定容器启动程序及参数,但是与CMD不同的是,会追加,不是覆盖

  12. 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端口

  1. 编写

    在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
    
  2. 构建

    #1.3是tag, 最后的 . 表示的是当前目录                                               
    docker build -f mydocker/Dockerfile2 -t mycentos:1.3 .
    
  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信息的容器

  1. 新建Dockerfile3

    FROM centos
    RUN yum install -y curl
    # 下载百度首页
    CMD ["curl", "www.baidu.com"]
    
  2. 新建镜像

    docker build -f mydocker/Dockerfile3 -t mybaidu .
    
  3. 运行

    # 查看新建镜像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

将镜像推送到阿里云以后再补充。。。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值