Docker

一、Docker作用与特征

docker中文官网传送门:https://www.docker-cn.com (自己看去)

二、Docker组件与元素

三个组件分别是:

三个基本要素分别是:

b28a5a6c1709746deb0aa2530be49af1

三、Docker安装

docker下载与安装教程传送门:http://get.daocloud.io (windows10安装完后记得去BIOS界面开启cpu虚拟化)

四、Docker容器生命周期

dockerevenstate

五、Docker网络模型

dockernet

docker容器的网络有五种模式:

六、Docker Volume(数据卷)

Docker中的数据可以存储在类似于虚拟机磁盘的介质中,在Docker中称为数据卷(Data Volume)。数据卷可以用来存储Docker应用的数据,也可以用来在Docker容器间进行数据共享。

数据卷呈现给Docker容器的形式就是一个目录,支持多个容器间共享,修改也不会影响镜像。使用Docker的数据卷,类似在系统中使用 mount挂载一个文件系统。

Docker Volume数据卷可以实现:

Docker数据持久化:

容器在运行期间产生的数据是不会写在镜像里面的,重新用此镜像启动新的容器就会初始化镜像,会加一个全新的读写入层来保存数据。

如果想做到数据持久化,Docker提供数据卷(Data volume)或者数据容器卷来解决问题,另外还可以通过commit提交一个新的镜像来保存产生的数据。

七、Dockerfile

Dockerfile是由一系列指令和参数构成的脚本,这些指令应用于基础镜像并最终创建一个新的镜像。它们简化了从头到尾的流程并极大的简化了部署工作。Dockerfile从FROM命令开始,紧接着跟随者各种方法,指令和参数。其产出为一个新的可以用于创建容器的镜像 。

Dockerfile常用指令

FROM指定基础镜像

放在第一行,其格式为:

#语法:
FROM <image> 
FROM <image>:<tag>
FROM <image>:<digest> 

LABEL镜像元数据

可以设置镜像的任何元数据,例如作者、版本等信息,格式为:

LABEL <key>=<value> <key>=<value> <key>=<value> ...

ENV设置环境变量

主要就是设置环境变量,之后的命令都可以用此变量进行赋值,格式如下:

ENV <key> <value>
ENV <key>=<value> ...

VOLUME定义匿名卷

VOLUME用于创建挂载点,即向基于所构建镜像创始的容器添加卷:

VOLUME ["/data"]

一个卷可以存在于一个或多个容器的指定目录,该目录可以绕过联合文件系统,并具有以下功能:

VOLUME 让我们可以将源代码、数据或其它内容添加到镜像中,而又不并提交到镜像中,并使我们可以多个容器间共享这些内容 .

COPY复制文件

主要就是构建镜像时,进行拷贝文件到镜像的指定路径下,格式为:

COPY <源路径>... <目标路径>
COPY ["<源路径1>",... "<目标路径>"]

ADD更高级的复制文件

ADD 指令和 COPY 的格式和性质基本一致。但是在 COPY 基础上增加了一些功能。比如<源路径>可以是一个 URL,这种情况下,Docker引擎会试图去下载这个链接的文件放到<目标路径>去。

EXPOSE设置监听端口

为镜像设置监听端口,容器运行时会监听改端口,格式为:

EXPOSE <port> [<port>/<protocol>...]

如,nginx镜像,监听了80端口

  EXPOSE 80

同时,也能指定协议名,如:

  EXPOSE 80/udp

ARG设置构建参数

该命令用于设置构建参数,该参数在容器运行时是获取不到的,只有在构建时才能获取。这也是其和ENV的区别。

ARG <name>[=<default value>]

使用举例:

arg author=yiuman
# 构建时,也可以替换了
# docker build --build-arg <varname>=<value>
docker build --build-arg author=xiaoming

RUN执行命令

在镜像的构建过程中执行特定的命令,并生成一个中间镜像。格式:

RUN <command>
或者
RUN ["executable", "param1", "param2"]

这也是很常用的一个功能了。 第一种后边直接跟shell命令 - 在linux操作系统上默认 /bin/sh -c - 在windows操作系统上默认 cmd /S /C

第二种是类似于函数调用。

可将executable理解成为可执行文件,后面就是两个参数。

两种写法比对:

RUN /bin/bash -c 'source $HOME/.bashrc; echo $HOME
RUN ["/bin/bash", "-c", "echo hello"]

CMD启动时命令

功能为容器启动时要运行的命令, 语法有三种写法

1. CMD ["executable","param1","param2"]
2. CMD ["param1","param2"]
3. CMD command param1 param2

就时shell这种执行方式和写法,第一种和第二种其实都是可执行文件加上参数的形式: 举例说明两种写法:

CMD [ "sh", "-c", "echo $HOME" ]
CMD [ "echo", "$HOME" ]

补充细节:这里边包括参数的一定要用双引号,就是双引号”,不能是单引号。千万不能写成单引号。原因是参数传递后,docker解析的是一个JSON array。

ENTRYPOINT启动默认命令

ENTRYPOINT 用于给容器配置一个可执行程序。也就是说,每次使用镜像创建容器时,通过 ENTRYPOINT 指定的程序都会被设置为默认程序。ENTRYPOINT 有以下两种形式:

ENTRYPOINT ["executable", "param1", "param2"]
ENTRYPOINT command param1 param2

ENTRYPOINTCMD 非常类似,不同的是通过docker run执行的命令不会覆盖 ENTRYPOINT,而docker run命令中指定的任何参数,都会被当做参数再次传递给ENTRYPOINTDockerfile只允许有一个 ENTRYPOINT 命令,多指定时会覆盖前面的设置,而只执行最后的ENTRYPOINT 指令 。

docker run运行容器时指定的参数都会被传递给ENTRYPOINT,且会覆盖 CMD 命令指定的参数。如,执行docker run <image> -d时,-d 参数将被传递给入口点 。

也可以通过docker run --entrypoint重写 ENTRYPOINT 入口点。如:可以像下面这样指定一个容器执行程序:

ENTRYPOINT ["/usr/bin/nginx"]

WORKDIR指定工作目录

用于在容器内设置一个工作目录:

WORKDIR /opt/docker/workdir

通过WORKDIR设置工作目录后,Dockerfile 中其后的命令RUNCMDENTRYPOINTADDCOPY等命令都会在该目录下执行。

USER指定当前用户

用于指定运行镜像所使用的用户:

USER yiuman

使用USER指定用户后,Dockerfile 中其后的命令RUNCMDENTRYPOINT都将使用该用户。镜像构建完成后,通过docker run运行容器时,可以通过-u参数来覆盖所指定的用户。

nginx Dockerfile Demo:

  # 注意:非注释第一行 必须以FROM 开头。
  # FROM 指定基础镜像,即以此镜像作为基础
  FROM nginx
  # 设置元数据,利用 docker inspect [镜像名称|镜像ID],即可查看。
  LABEL author="作者:yiuman"
  LABEL version="版本:v0.1"
  LABEL desc="说明:修改nginx首页提示"
  # 操作执行,这里直接修改了nginx的html的首页内容,/usr/share/nginx/html
  RUN echo 'hello,World' > /usr/share/nginx/html/index.html
  # 启动命令 不写时 会直接使用基础镜像的启动命令
  CMD ["nginx", "-g", "daemon off;"]

各容器的dockerfile实例的传送门:https://github.com/docker-library

八、Docker常用命令

九、踩过的坑

​ 刚开始用docker的时候,把docker for Mac 下载下来后,按照教程、随便看看文章就直接用上了。之所以用docker是因为公司需要弄微服务架构,运维部署这块选择了K8S与docker。然后自己就喜欢上了docker,本地跑下mysql,redis之类的。后来在微服务网络通信这块发现了容器内网络并不能通宿主机(即本地),折腾了大半天,终于在官网上找到了答案,如下:<传送门> dockernet

大致的意思是,macOS系统中存在网络限制,macOS没有docker0桥,因为这个接口是在虚拟机中的,宿主机无法ping通容器,从macOS主机无法访问docker (Linux)桥接网络。如果要从容器连接到主机,那么需要连接到host.docker.internal特殊的DNS,它将解析为主机使用的内部IP地址。网关可以用gateway.docker.internal

windows与linux下的docker是不存在这个问题的。