Docker的入门学习笔记

最近在学习Docker,顺手记录一下学习笔记。

在介绍Docker之前我们,我们先举个例子引入Docker。

小明一直在A市的某小区居住,有一天小明想搬到B市去住,这时他就得搬家,连人带家具等等一通搬,搬到B市,又得重新布置家居等等。想想这个是不是麻烦,假如小明又想去C市去,又得重复上述一通操作。随着科技的发展有了更先进的技术,我们可以搬楼,将房子整体搬迁,随搬随住。

见上图所示,小明相当于我们部署的项目,房子等相当于Docker,房子内的家居就相当于一个一个的容器

概念:

Docker是基于Go语言实现的开源项目

Docker的主要目标就是”build ,ship and Run any app anywhere”,意思就是我们通过对应用组件的封装分发部署运行等生命周期的管理,使用户的app(WEB项目或数据库应用)及其运行环境能够做到’一次封装,到处运行’。

Docker对比vm的优势:

  1. docker有着比虚拟机更少的抽象层。由于docker不需要Hypervisor实现硬件资源虚拟化,运行在docker容器上的程序直接使用的都是实际物理机的硬件资源。因此在cpu、内存利用率上docker将会在效率上有明显提升
  2. docker利用的是宿主机的内核,而不需要Guest OS,因此当新建一个容器时,docker不需要和虚拟机一样重新加载一个操作系统内核。避免引寻、加载操作系统内核等比较费时费资源的过程。当新建一个虚拟机,虚拟机软件需要加载GuestOs,新建过程时分钟级别的。而docker由于直接利用宿主机的操作系统,因此新建一个docker容器只需要几秒钟。
Docker容器 虚拟机(VM)
操作系统 与宿主机共享OS 宿主机OS上运行虚拟机OS
存储大小 镜像小,便于存储与传输 镜像大
运行性能 几乎无意外行损失 操作系统额外的cpu、内存消耗
移植性 轻便、灵活、适用于各系统 笨重,与虚拟化技术耦合高
硬件亲和性 面向软件开发者 面向运维
部署速度 快速,秒级 较慢

Docker帮助命令

docker version #docker版本信息

docker info    #docker镜像、容器、cpu、内存等相关信息

docker help    #查看相关的帮助命令

Docker镜像命令

docker images #查看本机镜像
# -a 显示本地所有镜像(包含中间镜像层)
# -q 只显示镜像ID
# --digests 显示镜像的摘要信息
# --no-trunc 显示完整镜像信息
docker search #搜索镜像
# -s [num]列出收藏数不小于 num 的镜像
# --no-trunc 显示完整镜像信息
docker pull #从hub上拉取镜像
docker pull mysql:5.6 #拉取5.6版本mysql镜像文件
docker rmi #删除镜像  
# -f 强制删除某镜像
# --no-trunc 显示完整镜像信息
docker rmi -f $(docker images -qa)
#删除全部镜像

查看镜像的变更历史:

docker history 镜像名[镜像ID]

镜像的commit操作:

我们可以commit提交容器副本使之成为一个新的镜像

docker commit -m=“提交的描述信息” -a=“作者” 容器ID 要创建的目标镜像名:[标签名]

Docker容器

新建并启动容器:

docker run [options] IMAGENAME
# --name 为运行容器起一个新名字
# --rm 停止容器,容器文件会自动删除
# -d 后台运行容器,并返回容器ID,即守护式启动
# -i 交互式运行容器,通常与 -t配合使用
# -t 为容器重新分配一个伪输入终端
# -e, --env=[], 指定环境变量,容器中可以使用该环境变量
# --link 表示该容器需要连接到其他容器,比如php需要连接到mysql
# -P 随机端口映射
# -p 指定端口映射,有以下四种格式:
 ip:hostPort:containerPort
 ip:containerPort
 hostPort:containerPort
 containerPort
# --volumes-from=[], 给容器挂载其他容器上的卷,挂载到容器的某个目录

官方run全部参数[点击]

列出运行的容器:

docker ps [options]
# -a 显示所有当前正在运行和过往运行的容器
# -l 显示最近创建运行的容器
# -n 显示最近n个创建的容器
# -q 静默模式,只显示容器编号

退出容器:

exit #容器停止并退出
ctrl + p +q #容器不停止 退出

启动 [重启] 容器:

docker start [restart] [容器ID或者容器名]

停止容器:

docker stop [名或ID]

强制停止容器:

docker kill [名或ID]

删除已停止的容器(历史运行的容器):

docker rm [容器ID]

#删除全部
docker rm -f $(docker ps -a -q)
docker ps -a -q|xargs docker rm -f

注意:使用centos:latest以后台启动一个容器

docker run -d centos

我们通过 docker ps -a 查看,发现容器已经退出,说明Docker容器后台运行,就必须有一个前台进程

容器的运行命令如果不是一直挂起的命令,比如top,tail等,就会自动退出

这是个Docker机制问题,假如我们的web容器,以nginx为例,正常情况下我们配置启动服务只需要启动响应的service即可。例如service nignx start ,但是这样nginx为后台守护模式,这就导致docker前台没有运行的应用,这样的容器后台启动后,会立刻自杀,因为它觉得没事可做。

查看容器日志:

docker logs -f -t --tail 容器ID
# -t 是加入时间戳
# -f 跟随最新的日志打印
# --tail 数字 显示最后多少条

查看容器内运行的进程:

docker top 容器ID

查看容器细节:

docker inspect 容器ID

进入正在运行的容器并以命令行交互:

docker exec -it 容器ID /bin/bash
#或
docker attach 容器ID

注意:上述两个的区别:attach 直接进入容器启动命令的终端,不会启动新的进程;exec 是在容器中打开新的终端,并且可以启动新的进程。并且exec 可以不进入命令交互查看容器相关信息,比如我们守护模式运行nginx,我们来查看nginx目录下文件,docker exec nginx容器ID ls

从容器内拷贝文件到主机上:

docker cp 容器ID:容器内路径 目的主机路径

Docker容器数据卷:

我们先来看一下Docker理念:将运行的环境打包成为容器来运行,运行可以伴随着容器,但是我们对于数据的要求是希望可以持久化;并且容器与容器之间可以共享数据。

Docker容器产生的数据,如果不通过docker commit生成新的镜像,使得数据作为镜像的一部分保存下来,那么容器被删除后,容器运行产生的数据自然就没了。

为了能保存数据在docker 我们使用卷。

概念:卷就是目录或文件,存在于一个或多个容器中,由Docker挂载到容器,但不属于联合文件系统,因此可以绕过UnionFileSystem提供一些用于持久存储或共享数据的特性。

卷的设计目的就是持久化,完全独立于容器的生存周期,因此Docker不会在容器删除时删除其挂载的数据卷。

特点:

  • 数据卷可以在容器之间共享或重用数据
  • 卷中的更改可以直接生效
  • 数据卷中的更改不会包含在镜像的更新中
  • 数据卷的生命周期一直持续到没有容器使用它为止

使用 -V命令添加数据卷:

docker run -it -v /宿主机绝对路径目录:/容器内目录 镜像名

#带权限(只读) 容器目录只读
docker run -it -v /宿主机绝对路径目录:/容器内目录:ro 镜像名

容器停止退出后,主机修改后数据是否同步:同步

使用弊端:

  • 出于可移植性和分享的考虑,使用 -v 主机目录:/容器目录 这种方式不能够直接在Dockerfile中实现
  • 由于宿主机的目录 不是每个主机都相同的,不能够保证每个宿主机都有同样特定的目录

使用Dockerfile形式添加数据卷:

dockerfile是用来构建Docker镜像的构建文件,由一系列的命令和参数构成的脚本。
简单示例:

FORM centos #本地镜像
VOLUME ["/datavolumeContainer1/","/datavolumeContainer2/"]
CMD /bin/bash

上述代码:volume 设置了两个容器卷,我们可以通过docker inspect 容器ID 查看对应宿主机目录,切记卷目录要用双引号.

数据卷构建过程:

  1. 编写dockerfile文件(定义了进程需要的一切东西,包括执行代码或者是文件、环境变量、依赖包、运行时环境、动态链接库、操作系统的发行版、服务进程和内核进行)
  2. docker build 生成新的自定义镜像文件
  3. docker run 运行(docker容器真正提供服务)

dockerfile文件内容说明:

  • 每条保留字指令都必须是大写字母且后面至少跟一个参数
  • 指令按照从上倒下顺序执行
  • #表示注册
  • 每条指令都会创建一个新的镜像层,并对镜像进行提交

docker执行dockerfile的流程分析:

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

从应用软件的角度分析Dockerfile 、Docer镜像与Docker容器关系:

Dockerfile 是软件的原材料

Docker镜像是软件的交付品

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

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

Dockerfile的相关指令及使用案例:

FROM #基础镜像,当前新镜像基于哪个镜像[类似继承]
MAINTAINER #镜像的维护者的姓名和邮箱地址
RUN #容器构建时需要运行的命令
EXPOSE#当前容器对外暴露的端口
WORKDIR#指定在创建容器后,终端默认登录进来的工作目录
ENV#用来在构建镜像过程中设置环境变量
ADD#将宿主机目录下的文件拷贝进镜像且ADD命令会自动处理URL和解压tar压缩包
COPY#类似ADD ,拷贝文件和目录到镜像中;将从构建上下文目录中<源路径>的文件/目录 复制到新的一层的镜像内的<目标路径>位置;即WORKDIR目录
VOLUME#容器数据卷,用于数据保存和持久化工作
CMD#指定一个容器启动时要运行的命令(dockerfile可以有多个CMD指令,但只有最后一个生效,CMD会被docker run 之后的参数替换)
ENTRYPOINT#指定一个容器启动时要运行的命令,与CMD一样
ONBUILD#当构建一个被继承的Dockerfile时运行命令,父镜像在被子继承后,构建子镜像过程中,父镜像的onbuild被触发 。形式:【from faher镜像】

注意:在docker run之后的命令参数会被当作参数 传递给ENTRYPOINT,之后形成新的命令组合;而如果使用CMD命令,那么docker run 之后的命令参数会替换掉 CMD 命令


示例:

自己构建一个centos镜像:改变它默认登录进来的目录,支持VIM编辑命令,可以使用ifconfig查看网卡相关配置

第一步:编写dockerfile如下:

FROM centos

ENV mypath /usr/local
WORKDIR $mypath
MAINTAINER houger<11@houger.cn>

ADD log.txt $mypath
#将宿主机的log文件拷贝到centos容器根目录

RUN yum -y install vim
RUN yum -y install net-tools

EXPOSE 80

CMD echo 'success .....'
CMD /bin/bash

第二步:构建新的基于dockerfile镜像

docker build -f /dockerfile -t 镜像名:TAG .
#末尾有个 . 表示当前路径

第三步:启动

docker run -it 新镜像名

在容器终端查看当前目录,发现已经切换到 /usr/local 并且支持 vimifconfig 命令


示例二:安装mysql

拉取mysql镜像

docker pull mysql:5.6

创建并运行容器,并-v形式添加数据卷,设置映射端口及连接密码

docker run --name myself_mysql -p 3388:3306
           -v /usr/local/myself_mysql/data:/var/lib/mysql
           -v /usr/local/myself_mysql/logs:/logs
           -v /usr/local/myself_mysql/conf:/etc/mysql/conf.d
           -e MYSQL_ROOT_PASSWORD=123456
           -d mysql:5.6          

上述代码我们自定了容器名为myself_mysql ,映射宿主机端口为3388添加了三个数据卷,分别映射日志、数据库数据、配置文件,并且以守护进程模式运行。

我们可以进入mysql的终端交互模式:

docker exec -it mysql_container_id /bin/bash

进来之后我们可以登录数据库:

mysql -uroot -p  #登录

创建表、插入数据等一通操作后,我们在宿主机映射目录即可查看到响应的数据,在宿主机终端我们可以以3388端口登录容器mysql。

发表评论

电子邮件地址不会被公开。 必填项已用*标注