Docker 的三个基本概念,镜像、容器、仓库

镜像:相当于一个操作系统,可以通过 Dockerfile 自行定制

容器:由镜像生成的一个实例

仓库:保存镜像,类似 github 管理代码,Docker 也有一个 DockerHub

安装

MacOS Docker 安装

手动下载

https://docs.docker.com/desktop/mac/install/

启动终端后,通过命令可以检查安装后的 Docker 版本

$ docker --version

查看各个命令或参数介绍

$ docker --help

镜像

查看本地已经下载的镜像列表

$ docker image ls

列表包含了 仓库名标签镜像 ID创建时间 以及 所占用的空间

如果列表很多的话,可以通过增加参数进行筛选

根据仓库名列出镜像

$ docker image ls ubuntu

列出特定的某个镜像,也就是说指定仓库名和标签

$ docker image ls ubuntu:18.04

除此之外还可以通过 –filter 参数或 -f,进行筛选

删除本地镜像

$ docker rmi -f imageID

到 docker 上查找镜像,例如 centos 镜像,可以根据需要找到不同版本的 centos

https://hub.docker.com/_/centos?tab=tags

制作镜像

一、使用 commit 构建镜像

先开启一个容器

$ docker run --name webserver -d -p 80:80 nginx

然后根据需求修改内容,例如下面我将 webserver 容器

$ docker exec -it webserver bash
root@3729b97e8226:/# echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html
root@3729b97e8226:/# exit
exit

我们修改了容器的文件,也就是改动了容器的存储层。我们可以通过 docker diff 命令看到具体的改动。

当我们运行一个容器的时候,我们做的任何文件修改都会被记录于容器存储层里。而 Docker 提供了一个 docker commit 命令,可以将容器的存储层保存下来成为镜像。就是在原有镜像的基础上,再叠加上容器的存储层,并构成新的镜像。以后我们运行这个新镜像的时候,就会拥有原有容器最后的文件变化。

docker commit 的语法格式为:

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

将容器保存为镜像:

$ docker commit \
    --author "Ryan Zheng <zhengjianhong95@gmail.com>" \
    --message "修改了默认网页" \
    webserver \
    nginx:v2

接下来就可以使用 docker image ls 看到新定制的镜像

查看镜像内的历史记录

$ docker history nginx:v2

二、使用 Dockerfile 定制镜像

Dockerfile 是一个文本文件,其内包含了一条条的 指令(Instruction),每一条指令构建一层,因此每一条指令的内容,就是描述该层应当如何构建。

新建一个文本文件,名称为 Dockerfile,内容如下

FROM nginx
RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html

FROM 指定基础镜像

RUN 执行命令行命令

构建镜像

Dockerfile 文件所在目录执行

$ docker build -t nginx:v3 .

命令的格式为 docker build [选项] <上下文路径/URL/->

在这里我们指定了最终镜像的名称 -t nginx:v3,构建成功后,我们可以像之前运行 nginx:v2 那样来运行这个镜像,其结果会和 nginx:v2 一样。

容器

查看所有容器

$ docker ps -a

查看容器的信息

$ docker inspect ContainerID

查看正在运行中的容器

$ docker container ls

删除容器

$ docker rm -vf ContainerID

开启容器

$ docker start ContainerID

停止容器

$ docker stop ContainerID

重启容器

$ docker restart ContainerID

运行容器

$ docker run --name webserver -d -p 8080:80 nginx

–name 指定容器的名称为 webserver

-p 8080:80 表示将本地的 8080 端口映射到容器的 80 端口,此时访问本机的 8080 端口即可访问容器内 NGINX 默认页面。

-d 容器在后台运行,并输出容器ID

nginx 表示使用 nginx 镜像

进入容器

$ docker exec -it ContainerID bash

持久化存储

在容器中管理数据主要有两种方式:

  1. 数据卷(Volumes)
  2. 挂载主机目录 (Bind mounts)

一、数据卷(Volumes)是一个可供一个或多个容器使用的特殊目录,可以在容器之间共享和重用,而且修改后立即生效,对数据卷的修改不会影响到镜像,数据卷默认一直存在,即使容器被删除

创建数据卷 ryan_vol

$ docker volume create ryan_vol

查看所有数据卷

$ docker volume ls

查看指定数据卷信息

$ docker volume inspect ryan_vol

删除数据卷

$ docker volume rm ryan_vol

数据卷是被设计用来持久化数据的,它的生命周期独立于容器,Docker 不会在容器被删除后自动删除数据卷,并且也不存在垃圾回收这样的机制来处理没有任何容器引用的 数据卷。如果需要在删除容器的同时移除数据卷。可以在删除容器的时候使用 docker rm -v 这个命令。

无主的数据卷可能会占据很多空间,要清理请使用以下命令

$ docker volume prune

启动一个挂载数据卷的容器

$ docker run -d -P --name web --mount source=ryan_vol,target=/usr/share/nginx/html nginx:alpine

二、挂载目录作为数据卷

$ docker run -d -P --name web --mount type=bind,source=/src/webapp,target=/usr/share/nginx/html       nginx:alpine

上面的命令加载本机的 /src/webapp 目录到容器的 /usr/share/nginx/html目录。这个功能在进行测试的时候十分方便,比如用户可以放置一些程序到本地目录中,来查看容器是否正常工作。本地目录的路径必须是绝对路径,以前使用 -v 参数时如果本地目录不存在 Docker 会自动为你创建一个文件夹,现在使用 --mount 参数时如果本地目录不存在,Docker 会报错。

仓库

仓库(Repository)是集中存放镜像的地方,目前 Docker 官方维护了一个公共仓库 Docker Hub,其中已经包括了数量超过 2,650,000 的镜像。大部分需求都可以通过在 Docker Hub 中直接下载镜像来实现。

登陆/退出 DockerHub

$ docker login
$ docker logout

查找官方仓库中的镜像

$ docker search centos

在查找的时候通过 --filter=stars=N 参数可以指定仅显示收藏数量为 N 以上的镜像。

下载镜像到本地

$ docker pull centos

docker 对免费用户有拉取镜像的限制,具体解决方法可以参考文章

https://www.chenshaowen.com/blog/how-to-cross-the-limit-of-dockerhub.html

将镜像推送到 DockerHub

$ docker push username/ubuntu:18.04

查看 DockerHub 账号下的公开镜像

$ docker search username

有时候使用 Docker Hub 这样的公共仓库可能不方便,用户可以创建一个本地仓库供私人使用

其他

一、官方的 nginx 镜像使用的 Linux 版本为 Debian,而且默认没有安装 vim 等常用工具,如果要使用这些工具的话,得手动安装,相关命令如下:

// 查看当前系统版本
cat /etc/issue

// 安装 systemctl、vim 等工具
apt-get update
apt-get upgrade -y
apt-get -y install vim
apt-get -y install systemctl

二、容器内访问宿主机网络

使用宿主机 IP、使用 host.docker.internal 这个特殊的DNS名称来解析宿主机IP

常见报错

mac 下安装完成后发现在终端执行docker命令报错 command not found

找到 docker 的安装路径,然后添加到 .zshrc 里面,最后执行下 source ~/.zshrc

export PATH=”$PATH:/Applications/Docker.app/Contents/Resources/bin”