Docker(二)

Posted by Run-dream Blog on October 14, 2018

镜像的内部结构

Base 镜像

含义:

  1. 不依赖于其他镜像,从SCRATCH创建
  2. 其他镜像可以扩展它

为什么centos的镜像只有200M: Linux操作系统由内核空间kernel和用户空间rootfs组成。 对于base镜像来说,底层直接调用Host的kernel,自己提供rootfs就OK。 base镜像提供的是最小安装的Linux发行版。

镜像的分层结构

新镜像是在base镜像上一层层叠加生成的。每安装一个软件,就在现有的基础上增加一层。

优势:资源共享

什么是Copy-on-Write: 只有在需要修改时才复制一份数据。

容器层 镜像层
容器启动时,被加载到顶部的可写层 容器层以下的镜像层
唯一可写 只读

所有的镜像层联合在一起组成一个统一的文件系统,上层的文件会覆盖下层的文件:

  1. 添加文件。在容器中创建文件时,新文件被添加到容器层
  2. 读取文件。从上往下依次在各镜像层中查找此文件。一旦找到,打开并读入内存。
  3. 修改文件。从上往下依次在各镜像层中查找此文件。一旦找到,复制到容器层,然后修改。
  4. 删除文件。从上往下依次在各镜像层中查找此文件。一旦找到,在容器层中记录下此删除操作。

容器层保存的是镜像变化的部分。

构建镜像

docker commit

步骤

  • 运行容器

    # 以交互模式进入容器
    docker run -it <container>
    
  • 修改容器

    # 执行所要修改的操作
    apt-get install vim
    
  • 将容器保存为新的镜像

    # 查看镜像名
    docker ps
      
    # 保存镜像
    docker commit <container_name> <image_name>
    

不推荐使用

  • 可重复性差
  • 安全性未知

但Dockerfile构建的底层也是通过该方式实现的。

Dockerfile

案例

Dockerfile:

FROM ubuntu
RUN apt-get update && apm-get install -y vim

docker build:

pwd
docker build -t ubuntu-with-vi .

-t 指定新镜像的名字 -f 制定dockerfile的路径,默认为build context下的dockerfile . 指明 build context 为当前目录,也就是ADD,COPY等命令添加文件到镜像的目录

docker history:

docker history ubuntu-with-vi

可以查看dockerfile的执行过程

调试:

docker run -it <imageid>

可以通过找到dockerbuild过程中失败的上一步得到的镜像id来进行调试

常用指令

  • FROM 指定base镜像

  • MAINTAINER 指定作者

  • COPY 从build context复制文件到镜像

  • ADD 从build context复制文件到镜像,并解压

  • ENV 设置环境变量

  • EXPOSE 暴露docker的某个端口

  • VOLUMN 将文件或目录声明为volumn

  • WORKDIR

    为后续指令指定执行目录

  • RUN 在镜像层中运行指令,安装应用和软件包,主要用于构建镜像。

    支持两种格式

    • shell

      RUN

    • exec

      RUN [“excutable”,”param1”,”param2”]

  • CMD 指定容器启动时默认执行指令。会在容器启动时 run 没有指定其他命令时候运行

    • 如果 docker run 指定了其他命令,CMD 会被忽略, 如

      docker run -it <image> /bin/bash
      
    • 如果 Docker file 有多个 CMD 指令, 只有最后一个 CMD 有效

  • ENTRYPOINT 容器启动时运行指令,可让容器以应用程序或服务的方式运行,一定会被执行

    支持两种格式:

    • bash

      ENTRYPOINT command param1 param2

      可以通过 CMD 来提供额外的参数。

      ENTRYPOINT ["/bin/echo", "Hello" ]
      CMD ["world"]
      
    • shell

      会忽略 CMD 或者 docker run 提供的参数

MySql 镜像 Dockerfile 案例

# 创建一个基于5.7.30版本的MySql
FROM mysql:5.7.30 
MAINTAINER don
EXPOSE 3306
LABEL version="0.1" description="Mysql服务器" by="don"
#设置免密登录
ENV MYSQL_ALLOW_EMPTY_PASSWORD yes
#将所需文件放到容器中
COPY /mysql/setup.sh /mysql/setup.sh #拷贝安装脚本
COPY /mysql/create_db.sql /mysql/create_db.sql #创建数据库
COPY /mysql/initial_data.sql /mysql/initial_data.sql #初始数据
COPY /mysql/privileges.sql /mysql/privileges.sql #设置密码和权限
#设置容器启动时执行的命令
CMD ["sh", "/mysql/setup.sh"]

常用操作子命令

  • images: 显示镜像列表
  • history: 显示镜像构建历史
  • commit: 从容器创建新镜像
  • build: 从Dockerfile 构建镜像
  • tag: 给镜像打tag
  • pull: 从registry下载镜像
  • push: 将镜像上传到registry
  • rmi: 删除Dokcker host上的镜像
  • search: 搜索Docker Hub中的镜像

Reference

《每天五分钟玩转Docker容器技术》

MySql 的 Dockerfile 编写