Docker是什么?

Docker是一个虚拟环境容器,可以将你的开发环境、代码、配置文件等一并打包到这个容器中,并发布和应用到任意平台中。

Docker的三个概念

① 镜像(Image):是一个包含有文件系统的面向Docker引擎的只读模板。任何应用程序运行都需要环境,而镜像就是用来提供这种运行环境的。例如一个Ubuntu镜像就是一个包含Ubuntu操作系统环境的模板。

② 容器(Container):类似于一个轻量级的沙盒,可以将其看作一个极简的Linux系统环境(包括root权限、进程空间、用户空间和网络空间等),以及运行在其中的应用程序。Docker引擎利用容器来运行、隔离各个应用。容器是镜像创建的应用实例,可以创建、启动、停止、删除容器,各个容器之间是是相互隔离的,互不影响。注意:镜像本身是只读的,容器从镜像启动时,Docker在镜像的上层创建一个可写层,镜像本身不变。

③ 仓库(Repository):Docker用来集中存放镜像文件的地方。注意与注册服务器(Registry)的区别:注册服务器是存放仓库的地方,一般会有多个仓库;而仓库是存放镜像的地方,一般每个仓库存放一类镜像,每个镜像利用tag进行区分,比如Ubuntu仓库存放有多个版本(12.04、14.04等)的Ubuntu镜像。

Docker的安装和卸载

可查看官方教程,这里以CentOS系统和Ubuntu系统为例。

CentOS

安装

① 安装所需软件包与驱动程序

1
sudo yum install -y yum-utils device-mapper-persistent-data lvm2

② 设置仓库源

  • 官方源(比较慢)

    1
    sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
  • 阿里源

    1
    sudo yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
  • 清华大学源

    1
    sudo yum-config-manager --add-repo https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/centos/docker-ce.repo

③ 安装Docker(默认安装最新版本)

1
sudo yum install docker-ce docker-ce-cli containerd.io

安装过程中会提示是否接受GPG密钥,请选是。

如果要安装指定版本,可使用如下命令查可用版本(按版本号从高到低对结果进行排序):

1
yum list docker-ce --showduplicates | sort -r

例:

1
2
3
4
docker-ce.x86_64  3:18.09.1-3.el7                     docker-ce-stable
docker-ce.x86_64 3:18.09.0-3.el7 docker-ce-stable
docker-ce.x86_64 18.06.1.ce-3.el7 docker-ce-stable
docker-ce.x86_64 18.06.0.ce-3.el7 docker-ce-stable

并通过其版本号安装特定版本,即第二列第一个:一直到第一个-中间的字符。

1
sudo yum install docker-ce-18.09.1 docker-ce-cli-18.09.1 containerd.io

注:Docker 安装完默认未启动。并且已经创建好 docker 用户组,但该用户组下没有用户。

④ 启动Docker

1
sudo systemctl start docker

⑤ 验证

通过运行 hello-world 映像来验证是否正确安装:

1
sudo docker run hello-world

卸载

删除安装包:

1
yum remove docker-ce

删除镜像、容器、配置文件等内容:

1
rm -rf /var/lib/docker

卸载旧版本:

1
2
3
4
5
6
7
8
sudo yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine

Ubuntu

安装

自动安装:

1
curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun

也可以使用国内 daocloud 一键安装命令:

1
curl -sSL https://get.daocloud.io/docker | sh

手动安装:

① 更新apt包索引

1
sudo apt-get update

② 安装apt依赖包,用于通过https来获取仓库:

1
sudo apt-get install apt-transport-https ca-certificates curl gnupg-agent software-properties-common

③ 添加Docker的官方GPG密钥:

1
curl -fsSL https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu/gpg | sudo apt-key add -

9DC8 5822 9FC7 DD38 854A E2D8 8D81 803C 0EBF CD88 通过搜索指纹的后8个字符,验证您现在是否拥有带有指纹的密钥。

1
sudo apt-key fingerprint 0EBFCD88

④ 设置稳定版仓库

1
sudo add-apt-repository "deb [arch=amd64] https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu/ $(lsb_release -cs) stable"

⑤ 更新apt包索引

1
sudo apt-get update

⑥ 安装Docker

1
sudo apt-get install docker-ce docker-ce-cli containerd.io

如果要安装指定版本,可使用如下命令查可用版本(按版本号从高到低对结果进行排序):

1
apt-cache madison docker-ce

例:

1
2
3
4
5
docker-ce | 5:18.09.1~3-0~ubuntu-xenial | https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu  xenial/stable amd64 Packages
docker-ce | 5:18.09.0~3-0~ubuntu-xenial | https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu xenial/stable amd64 Packages
docker-ce | 18.06.1~ce~3-0~ubuntu | https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu xenial/stable amd64 Packages
docker-ce | 18.06.0~ce~3-0~ubuntu | https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu xenial/stable amd64 Packages
...

并通过其版本号安装特定版本,即第二列第一个:一直到第一个-中间的字符。

1
sudo apt-get install docker-ce-18.09.1 docker-ce-cli-18.09.1 containerd.io

注:Docker 安装完默认未启动。并且已经创建好 docker 用户组,但该用户组下没有用户。

⑦ 启动Docker

1
sudo service docker start

⑧ 验证

通过运行 hello-world 映像来验证是否正确安装:

1
sudo docker run hello-world

卸载

删除安装包:

1
sudo apt-get purge docker-ce

删除镜像、容器、配置文件等内容:

1
sudo rm -rf /var/lib/docker

卸载旧版本

1
sudo apt-get remove docker docker-engine docker.io containerd runc

加入用户组

Docker需要用户具有sudo权限,为了避免每次命令都输入sudo,建议将用户加入Docker用户组:

① 添加Docker分组

1
sudo groupadd docker

② 将当前用户添加到分组

1
sudo usermod -aG docker $USER

③ 重启服务

1
sudo service docker restart

④ 切换当前会话到新组

1
newgrp - docker

配置镜像加速

国内从DockerHub拉取镜像速度慢,此时可以配置镜像加速器。Docker官方和国内很多云服务商都提供了国内加速器服务。例如:

注:阿里云须登录,从左侧菜单选中镜像加速器获取专属地址。

这里以Ubuntu16.04+、Debian8+、CentOS7的配置为例,在 /etc/docker/daemon.json中写入如下内容(如果文件不存在请新建该文件):

1
2
3
4
5
6
{
"registry-mirrors": ["https://registry.docker-cn.com",
"http://hub-mirror.c.163.com",
"https://docker.mirrors.ustc.edu.cn"
]
}

多个镜像源则以,分割。

之后重启服务:

1
2
sudo systemctl daemon-reload
sudo systemctl restart docker

使用

docker常用命令

1
2
3
docker --help #查看docker命令
docker info #docker 详细信息,镜像和容器
docker version #查看docker版本

常用镜像命令

查看镜像

1
2
3
4
5
docker images #查看docker镜像
docker images -a #列出本地所有的镜像
docker images -q #只显示镜像ID
docker images --digests #显示镜像的摘要信息
docker images --no-trunc #显示完整的镜像信息

具体列解释含义:

  • REPOSITORY:镜像仓库源
  • TAG:镜像的标签
  • IMAGE ID:镜像id
  • CREATED:创建时间
  • SIZE:大小

注:同一个仓库源可以有多个TAG,表示这个仓库源的不同版本,我们使用REPOSITORY:TAG来定义不同的镜像。如果不指定一个镜像的版本标签,例如只使用tomcat,docker将默认使用tomcat:latest镜像

查找镜像

1
2
docker search tomcat #从Docker Hub上查找tomcat镜像
docker search --filter=stars=300 tomcat #从Docker Hub上查找关注度(stars)大于300的tomcat镜像

下载镜像

1
docker pull tomcat #下载tomcat镜像,相当于:docker pull tomcat:latest

删除镜像

1
2
3
4
docker rmi redis #单个镜像删除,相当于:docker rmi redis:latest
docker rmi -f redis #强制删除(针对基于镜像有运行的容器进程)
docker rmi -f redis tomcat nginx #多个镜像删除,不同镜像间以空格间隔
docker rmi -f $(docker images -q) #删除本地全部镜像

容器命令

只有在镜像的基础上才能运行容器命令

查看容器

1
2
docker ps -a #-a 是查看当前所有正在运行的容器
docker ps -q #只显示容器ID

容器启动

1
2
3
4
docker run -i -t --name mycentos #新建并启动容器,参数:-i 以交互模式运行容器;-t 为容器重新分配一个伪输入终端;--name 为容器指定一个名称, 相当于: docker run -it mycentos
docker run -d mycentos #后台启动容器,参数:-d 以守护进程方式启动容器
docker start 容器id或容器名 #启动容器
docker restart 容器id或容器名 #重启容器

容器停止

1
2
docker kill 容器id或容器名
docker stop 容器id或容器名

进入容器

1
2
3
4
#放在镜像名后的是命令,这里我们希望有个交互式Shell,因此用的是/bin/bash
docker attach 容器id或容器名 /bin/bash #进入容器正在执行的终端,不会启动新的终端进程
docker run -it 容器id或容器名 /bin/bash #使用run方式在创建时进入
docker exec -it 容器id或容器名 /bin/bash #进入容器后,开启一个新的终端,可以在里面操作

退出容器

1
2
exit #关闭容器并退出
快捷键:Ctrl + P + Q #仅退出容器,不关闭

挂载

1
docker run -it -v /宿主机目录:/容器目录 镜像名 /bin/bash #-v 容器启动时会将宿主机目录挂载到容器里

容器内拷贝文件到主机

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

容器连接

可以通过 -P-p参数来指定端口映射,实现外部通过网络端口来访问运行在Docker容器内的服务,例如:

1
2
docker run -d -P training/webapp python app.py
docker run -d -p 5000:5000 training/webapp python app.py
  • -P :是容器内部端口随机映射到主机的高端口。
  • -p:是容器内部端口绑定到指定的主机端口。

外部可通过SSH,使用ip+绑定的主机端口号进行容器访问。

利用Dockerfile创建镜像

Dockerfile可以理解为一种配置文件,用来告诉docker build命令应该执行哪些操作。可参照官方说明。

Dockerfile组成

Dockerfile是由一行行命令语句组成,并且支持已#开头的注释行。

一般来说,可以将Dockerfile分为四个部分:

  • 基础镜像(父镜像)信息指令FROM
  • 维护者信息指令MAINTAINER
  • 镜像操作指令RUNEVNADDWORKDIR
  • 容器启动指令CMDENTRYPOINTUSER

Dockerfile示例

下面是一段简单的Dockerfile的例子:

首先创建Dockerfile文件:

1
touch Dockerfile

然后编辑该文件,输入内容:

1
2
3
4
5
6
7
8
FROM python:3.6
MAINTAINER zqy <zqy@gmail.com>
COPY . /app
WORKDIR /app
RUN pip install -r requirements.txt
EXPOSE 5000
ENTRYPOINT ["python"]
CMD ["app.py"]

  • 1、从Docker Hubpullpython 3.6的基础镜像
  • 2、构建者的信息(自己定义)
  • 3、copy当前目录.到容器中的/app目录下
  • 4、指定工作路径为/app
  • 5、安装依赖包
  • 6、暴露5000端口
  • 7、执行app.py

最后在Dockerfile文件所在目录执行:

1
docker build -t zqy/demo:v1 .
  • -t是为新镜像设置仓库和名称,其中zqy为仓库名,demo为镜像名,:v1为版本标签(不添加为默认 latest ),.为当前路径

常用指令集

FROM

用于指定基础的images,一般格式为FROM <image>orFORM <image>:<tag>,所有的 Dockerfile都用该以FROM开头,FROM命令指明Dockerfile所创建的镜像文件以什么镜像为基础,FROM以后的所有指令都会在FROM的基础上进行创建镜像。

MAINTAINER

MAINTAINER 是用于指定镜像创建者和联系方式,一般格式为MAINTAINER <name>

COPY

用于复制本地主机的<src>(为 Dockerfile 所在目录的相对路径)到容器中的 <dest>。当使用本地目录为源目录时,推荐使用COPY。一般格式为COPY <src> <dest>COPY ["<src>",... "<dest>"](特别适合路径中带有空格的情况)。

ADD

不仅能够将构建命令所在的主机本地的文件或目录,而且能够将远程URL所对应的文件或目录,作为资源复制到镜像文件系统。可以认为是增强版的COPY,支持将远程URL的资源加入到镜像的文件系统。一般格式为ADD <src> <dest>ADD ["<src>",... "<dest>"](特别适合路径中带有空格的情况)。

ENV

设置环境变量,可以被后面的所有指令中使用,格式为ENV <key> <value> ...,如设置JAVA环境变量:

1
2
ENV JAVA_HOME /opt/software/jdk1.8.0_161
ENV PATH $JAVA_HOME/bin:$PATH

WORKDIR

用于配合RUNCMDENTRYPOINT命令设置当前工作路径。可以设置多次,如果是相对路径,则相对前一个WORKDIR命令。默认路径为/。一般格式为WORKDIR /path/to/work/dir

RUN

用于容器内部执行命令。每个RUN命令相当于在原有的镜像基础上添加了一个改动层,原有的镜像不会有变化。一般格式为RUN <command> 。例如要安装python依赖包,做法如下:

1
RUN pip install -r requirements.txt

EXPOSE

用来指定对外开放的端口。一般格式为EXPOSE <port> [<port>...]

ENTRYPOINT

让容器表现得像一个可执行程序一样。一个Dockerfile中只能有一个ENTRYPOINT,如果有多个,则最后一个生效。

ENTRYPOINT 命令有两种格式:

  • ENTRYPOINT ["executable", "param1", "param2"] :推荐使用的 exec形式
  • ENTRYPOINT command param1 param2shell 形式

例如要将python镜像变成可执行的程序,可以这样去做:

1
ENTRYPOINT ["python"]

CMD

用于启动容器时默认执行的命令,CMD命令可以包含可执行文件,也可以不包含可执行文件。不包含可执行文件的情况下就要用ENTRYPOINT指定一个,然后CMD命令的参数就会作为ENTRYPOINT的参数。

CMD 命令有三种格式:

  • CMD ["executable","param1","param2"]:推荐使用的 exec 形式。
  • CMD ["param1","param2"]:无可执行程序形式
  • CMD command param1 param2:shell 形式。

一个Dockerfile中只能有一个CMD,如果有多个,则最后一个生效。而CMDshell形式默认调用/bin/sh -c执行命令。

CMD命令会被Docker命令行传入的参数覆盖:docker run busybox /bin/echo Hello Docker会把CMD里的命令覆盖。

USER

指定运行容器时的用户名或UID或GID,后续的操作都会使用指定用户。格式:USER userUSER user:groupUSER uidUSER uid:gidUSER user:gidUSER uid:group

例:

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