docker学习笔记:镜像和容器的使用

个人学习笔记,摘抄自 https://yeasy.gitbook.io/docker_practice

docker 简介

Docker 使用 Google 公司推出的 Go 语言 进行开发实现,基于 Linux 内核的 cgroup,namespace,以及 OverlayFS 类的 Union FS 等技术,对进程进行封装隔离,属于 操作系统层面的虚拟化技术。由于隔离的进程独立于宿主和其它的隔离的进程,因此也称其为容器。

基本概念

  • 镜像
    Docker 镜像是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。镜像不包含任何动态数据,其内容在构建之后也不会被改变。 镜像使用分层存储的结构, 且可以继承复用的。
  • 容器
    容器是镜像运行时的实体,可以被创建、启动、停止、删除、暂停等。容器的实质是进程,但与直接在宿主执行的进程不同,容器进程运行于属于自己的独立的命名空间。容器也是分层存储的,每个容器运行时以镜像为基础创建当前的容器存储层。容器存储层的生存周期和容器一样,容器消亡时,容器存储层也随之消亡。
  • 仓库
    Docker Registry是一个集中的存储、分发镜像的服务。我们可以通过 <仓库名>:<标签> 的格式来指定具体是这个软件哪个版本的镜像。仓库名经常以 两段式路径 形式出现,比如 jwilder/nginx-proxy,前者往往意味着 Docker Registry 多用户环境下的用户名,后者则往往是对应的软件名。

使用镜像

修改国内镜像源

mac: 在 Perferences -> Docker Engine 中添加以下配置, 再选择应用和重启就好了。

{
  "registry-mirrors": [
    "https://hub-mirror.c.163.com",
    "https://mirror.baidubce.com"
  ]
}

**linux

  • 使用systemctl cat docker 查看 ExecStart= 的位置,修改对应文件内容。
  • 编辑 /etc/docker/daemon.json,输入上面的内容。
  • 重启
sudo systemctl daemon-reload
sudo systemctl restart docker

使用镜像

获取镜像
docker pull [选项] [Docker Registry 地址[:端口号]/]仓库名[:标签]

默认仓库地址: Docker Hub (docker.io)
仓库名:<用户名>/<软件名>, 所谓的用户名可以理解为项目组的东西,默认是 library
例如: docker pull ubuntu:18.04

运行

ubuntu:18.04 为例. 如果需要启动里面的bash并且镜像交互操作的话,可执行

docker run -it --rm ubuntu:18.04 bash

参数解释:

  • -it :-i 进行交互式操作, -t 终端
  • --rm: 容器退出后即删除,这里实验用,所以直接删掉节约空间。
  • ubuntu:18.04 : 使用指定的镜像为基础启动容器
  • bash: 放在镜像后的命令,使用 bash 进行交互。
列出镜像

查看镜像(默认显示顶层镜像)

docker image ls 

其他拓展查询

# 查询 ubuntu 的镜像
docker image ls ubuntu

# 查询指定镜像
docker image ls unbuntu:18.04

# 过滤镜像,  mongo:3.2之后的,  before 之前
docker image ls -f since=mongo:3.2

# 根据label过滤
docker image ls -f label=com.example.version=0.1

由于镜像的分层结构,且能够继承复用,实际空间比列出的所有空间要小。
查看镜像/容器/数据卷占用空间命令为

docker system df

无标签的镜像被称为虚悬镜像,一般虚悬镜像已经失去了价值,可以随意删除的。删除命令

docker image prune
删除镜像
docker image rm [选项] <镜像1> [<镜像2> ...]

镜像可以是 镜像短id、镜像长id、镜像名、镜像摘要

删除过程

  • untagged:取消标签,由于镜像的分层结构,一个镜像可以对应多个标签,只有镜像没有任何标签时才回被删除
  • deleted:真正删除镜像, 如果镜像启动的容器还在,也不会删除,容器是基于镜像的。

使用 docker image ls 配合批量删除

docker image rm $(docker image ls -q redis)
commit

将容器的存储层保存下来成为镜像。
但是不要使用commit定制镜像,应使用Dockerfile完成。

docker commit [选项] <容器ID或容器名> [<仓库名>[:<标签>]]


示例:
docker commit \
    --author "作者" \
    --message "修改了默认网页" \
    webserver \
    nginx:v2

修改容器后,可以用 docker diff 容器名查看具体改动。

使用docker commit意味着所有对镜像的操作都是黑箱操作,生成的镜像也被称为黑箱镜像. 非常不利于维护。且对容器镜像的修改只是在当前层镜像标记、添加、修改,不会修改上层。使用commit会使得镜像很臃肿。

Dockerfile

镜像的定制实际上就是定制每一层所添加的配置、文件,因此将这些操作写入一个脚本,就能解决前面说的透明、体积的问题。
Dockerfile包含了一条条的 指令(Instruction),每一条指令构建一层,因此每一条指令的内容,就是描述该层应当如何构建。

示例: 定制nginx镜像,修改index.html

FROM nginx
RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html
  • FROM 指定基础镜像。且必须指定一个基础镜像,如服务类 nginx、redis、mongo、mysql、httpd、php、tomcat, 语言类 node、openjdk、python、ruby、golang,系统类 ubuntu、debian、centos、fedora、alpine。 空白镜像 scratch。
  • RUN 执行命令。 两种格式
    • shell 格式, RUN <命令>
    • exec 格式, RUN ["可执行文件", "参数1", "参数2"]

一个示例:

FROM debian:stretch

RUN set -x; buildDeps='gcc libc6-dev make wget' \
    && apt-get update \
    && apt-get install -y $buildDeps \
    && wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz" \
    && mkdir -p /usr/src/redis \
    && tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=1 \
    && make -C /usr/src/redis \
    && make -C /usr/src/redis install \
    && rm -rf /var/lib/apt/lists/* \
    && rm redis.tar.gz \
    && rm -r /usr/src/redis \
    && apt-get purge -y --auto-remove $buildDeps

因为每个指令都会构建一层,所以通过 && 将所有命令串联起来,简化构建。且示例中最后一行删除类为了编译构建所需要的软件,将无关的东西清理掉,不然会一直跟着镜像。

另Dockerfile 支持 \ 进行换行,# 注释。

定制镜像

docker build [选项] <上下文路径/URL/->

如在 Dockerfile文件所在命令执行:
docker build -t nginx:v3 .

关于上下文路径:
上面例子构建的上下文路径为.,这个是表示将当前目录作为上下文路径。Docker运行时分为Docker引擎(服务端)和客户端,使用REST API镜像交互(所以还能操作远程服务端)。而构建镜像时docker build会将路径下的所有内容打包上传给Docker引擎。 Dockerfile中可以通过相对路径访问这些文件。 另外也可以使用.dockerignore剔除不需要作为上下问传递给Docker引擎。 默认构建文件为上下文路径中的 Dockerfile,也可以 -f 指定其他文件。

其他构建方式

# 使用ulr构建,如git仓库 master分支,amd64/hello-word 目录
docker build` -t hello-world https://github.com/docker-library/hello-world.git#master:amd64/hello-world

# 使用tar压缩包构建
docker build http://server/context.tar.gz

# 从标准输入读取Dockerfile
docker build - < Dockerfile
或
cat Dockerfile | docker build -

# 标准输入读压缩包
docker build - < context.tar.gz
Dockerfile 指令
  • FROM 指定基础镜像

  • RUN 执行命令. 详见 Dockerfile

  • COPY 复制文件

    • 从上下文目录中复制文件到镜像中,源路径可多个,支持通配符。两种格式:
      • COPY [--chown=<user>:<group>] <源路径>... <目标路径>
      • COPY [--chown=<user>:<group>] ["<源路径1>",... "<目标路径>"]
    • 源文件元数据保留,如读写权限。
    • –chown 可改变文件所属用户&组
    • 源文件为文件夹,则复制文件夹下的内容到目标路径
  • ADD 高级复制

    • 格式基本和 COPY 一致
    • 源路径支持url,默认权限600,修改权限或解压需另用RUN
    • 源文件为tar时(格式 gzip,bzip2,xz),支持自动解压
    • 不实用,不建议使用。会时构建缓存失效,构建变慢。
  • CMD 容器启动命令

    • 两种格式:
      • shell: CMD <命令>
      • exec: CMD ["可执行文件", "参数1", "参数2"...]。 推荐这个模式,shell最终还是解析成这样
      • 参数列表格式:CMD ["参数1", "参数2"...]。在指定了 ENTRYPOINT 指令后,用 CMD 指定具体的参数。
    • 用于指定默认的容器主进程的启动命令。docker不是虚拟机,容器就是进程,所以需要启动命令。
    • docker run后面的执行命令优先级比这个高
    • 容器不是虚拟机,应用都是前台执行,无后台服务概念。对于容器而言,其启动程序就是容器应用进程,容器就是为了主进程而存在的,主进程退出,容器就失去了存在的意义,从而退出。
      • 错误示例:CMD service nginx start 解释;sh为主进程,sh执行完就退出了,且没有后台进程。
      • 正确使用:CMD ["nginx", "-g", "daemon off;"]
  • ENTRYPOINT 入口点

    • 目的和 CMD 一样,都是在指定容器启动程序及参数。略繁琐
    • 指定 ENTRYPOINT 后,CMD 不再直接运行,而且作为产生传递给 ENTRYPOINT, 实际执行变为 <ENTRYPOINT> "<CMD>" (主要利用cmd作为参数这点使用)
    • 如 docker run 后面 CMD 可以当作参数,可以利用这个在执行docker run时指定参数, 让镜像变成像命令一样使用
  • ENV 设置环境变量

    • 格式:(有空格加引号)
      -ENV <key> <value>
      • ENV <key1>=<value1> <key2>=<value2>...
    • 支持的指令:ADD、COPY、ENV、EXPOSE、FROM、LABEL、USER、WORKDIR、VOLUME、STOPSIGNAL、ONBUILD、RUN
  • ARG 构建参数

    • 效果同 ENV, 但只在构建时生效,容器运行后不生效。 但在docker history中可以看到所有值
    • 构建命令 docker build 中可用 --build-arg <参数名>=<值> 来覆盖对应的值。 1.13版前-arg的参数必须Dockerfile中指定
    • FROM 会分割 ARG 的生效范围。 FROM 后面的指令读取不到ARG,需重设
  • VOLUME 定义匿名卷

    • 格式:
      • VOLUME ["<路径1>", "<路径2>"...]
      • VOLUME <路径>
    • 容器运行时动态数据文件应保存与卷中。可以事先指定某些目录挂载为匿名卷,这样在运行时如果用户不指定挂载,其应用也可以正常运行,不会向容器存储层写入大量数据
    • 运行时可覆盖 docker run -d -v mydata:/data xxxx mydate 命名卷挂载到/data上了,替代了匿名卷的配置
  • EXPOSE 暴露端口

    • 格式:EXPOSE <端口1> [<端口2>...]
    • 仅声明,不会自动在宿主进行端口映射. 运行时使用 -p <宿主端口>:<容器端口> 才是将容器的对应端口服务公开给外界访问。
  • WORKDIR 指定工作目录

    • 指定工作目录后,后续各层的当前目录都是指定的目录。 (由于分层结构每个指令都是处于不同的容器中,连续的两个指令的当前目录也就不连续了)。 Dockerfile不是shell
  • USER 指定当前用户

    • 格式:USER <用户名>[:<用户组>]
    • USER 指令和 WORKDIR 相似,都是改变环境状态并影响以后的层。 用户需是已存在的。 如需再执行期间切用户,建议使用gosu(需要下载)
  • HEALTHCHECK 健康检查

    • 格式:
      • HEALTHCHECK [选项] CMD <命令>:设置检查容器健康状况的命令
      • HEALTHCHECK NONE:如果基础镜像有健康检查指令,使用这行可以屏蔽掉其健康检查指令
    • 告诉docker如何判断容器状态是否正常, 1.12新增指令。 (容器内死锁的情况Docker不能自行判断)
    • 参数:--interval=<间隔> 默认30s; --timeout=<时长> 超时时间 30s;--retries=<次数> 重试次数
  • ONBUILD 特殊指令

    • 格式:ONBUILD <其他执行>
    • 后面跟的是其它指令,比如 RUN, COPY。只有作为基础镜像构建下一级镜像时才被执行
  • LABEL 元数据

    • LABEL <key>=<value> <key>=<value> <key>=<value> ...
    • 可以用来声明镜像作者,文档地址等
  • SHELL

    • SHELL ["executable", "parameters"]
    • 可以指定 RUN ENTRYPOINT CMD 指令的 shell,Linux 中默认为 ["/bin/sh", “-c”]bu

操作容器

新建并启动

如启动一个bash终端,并进行交互

docker run -t -i ubuntu:18.04 /bin/bash
  • -t 分配一个伪终端并绑定到容器的标准输入上,
  • -i 打开容器的标准输入

当利用 docker run 来创建容器时,Docker 在后台运行的标准操作包括:

  • 检查本地是否存在指定的镜像,不存在就从公有仓库下载
  • 利用镜像创建并启动一个容器
  • 分配一个文件系统,并在只读的镜像层外面挂载一层可读写层
  • 从宿主主机配置的网桥接口中桥接一个虚拟接口到容器中去
  • 从地址池配置一个 ip 地址给容器
  • 执行用户指定的应用程序
  • 执行完毕后容器被终止
后台运行

添加 -d 参数

此时可以通过获取容器的输出信息

docker container logs <container ID or NAMES>

终止容器

docker container stop <id or names>

查询终止状态容器

docker container ls -a

重启命令

  • start 重启一个已停止的容器
  • restart 重启运行中的容器

进入容器

  • attach 命令
    • docker attach <id>, exit后容器会停止
  • exec
    • docker exec -it <id> -it 分配伪终端,和命令提示符

导入和导出

  • docker export <id> 到处容器快照

    • 如: docker export xxxx > ubuntu.tar
  • docker import 将容器快照文件导入为镜像

    • 如:cat ubuntu.tar | docker import - test/ubuntu:v1.0
    • 或使用url:docker import http://example.com/exampleimage.tgz example/imagerepo

删除

删除处于终止状态的容器

docker container rm <id>

清理所有终止状态的容器

docker container prune

访问仓库

拉取镜像

  • docker search <name> 搜索镜像
  • docker pull [选项] [Docker Registry 地址[:端口号]/]仓库名[:标签]

推送镜像

首先需要先登陆一下,然后输入用户名和密码。(如果用的公有仓库需要先去 https://hub.docker.com 注册一个账号)

docker login

# 退出
docker logout

然后推送镜像

docker tag ubuntun:18.04 <username>/ubuntu:18.04

docker push <username>/ubuntu:18.04
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值