Docker容器从入门到入门

1、概述

一、容器为解决什么问题

如今的软件系统已经很是复杂。一方面包含多种服务,这些服务有本身所依赖的库和软件包;另外一方面存在多种部署环境。这就产生了一个问题:如何让每种服务可以在全部的部署环境中顺利运行?git

容器的设计理念由码头上的集装箱而来,经过集装箱的标准化相互隔离实现软件系统依赖的打包与运行隔离。redis

二、Docker是什么

Docker如今几乎是容器的代名词,它同时也是Docker公司的名字。不过咱们一般所说的Docker指的是容器或者容器技术docker

使用Docker以前,须要安装它。以CentOS为例:shell

# yum install docker-ce
# systemctl start docker
复制代码

以后即可以使用docker命令操做容器或镜像了(容器与镜像下文会讲到)。centos

三、容器优势

  • 一致的运行环境:Docker的镜像提供了除内核外完整的运行时环境,确保了应用运行环境一致性;
  • 极其轻量:只打包了必要的Bin/Lib,容器不是模拟一个完整的操做系统,而是对进程进行隔离,是进程级别的
  • 秒级部署:根据镜像的不一样,容器的部署大概在毫秒与秒之间(比虚拟机强不少);
  • 易于移植:一次构建,随处部署;
  • 弹性伸缩:Kubernetes、Swam、Mesos这类开源、方便、好使的容器管理平台有着很是强大的弹性管理能力。

四、容器的主要应用场景

  • 持续集成和持续部署(CI/CD): 经过Docker完成持续集成管道自动化和应用部署;
  • 微服务

2、Docker中的概念及使用

一、镜像(Image)

Docker镜像是Docker容器运行的基础,没有Docker镜像,就没有Docker容器。镜像与容器就像是面向对象程序设计中的实例同样,镜像是静态的定义,容器是镜像运行时的实体数组

镜像是一个特殊的文件系统,除了提供容器运行时所需的程序资源配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。 镜像不包含任何动态数据,其内容在构建以后也不会被改变安全

(1) 镜像的获取方式一般有3种:

  1. 经过Dockerhub提供;
  2. 经过某一个已经运行的容器生成镜像(下文讲);
  3. 使用Dockerfile生成(下文讲);

上面是使用pull子命令从DockerHub下载centos:latest镜像,其中centos是镜像名,latest是标签名。使用docker images命令已经能够看到刚下载的centos镜像了。bash

(2) 镜像经常使用操做

从仓库拉取镜像: # docker pull <image_id> 有时候可能须要先登陆docker login <registry_host>服务器

从容器生成镜像: # docker commit <container_id> <image_name>网络

删除镜像: # docker rmi [-f] <image_id | image_name>

转移镜像: # docker save <image_id | image_name> a_file_name.tar 保存镜像到文件 # docker load a_file_name.tar 加载镜像文件到本地镜像库

二、容器(Container)

容器是镜像运行时的实体。容器能够被建立、启动、中止、删除、暂停等。 容器的实质是进程,但与直接在宿主执行的进程不一样,容器进程运行于属于本身的独立的命名空间。

(1) 启动容器

Docker启动容器的命令格式:Usage: docker run [OPTIONS] IMAGE [COMMAND] [ARG...],如今使用咱们下载的centos镜像启动一个容器:

上图使用run命令启动一个容器(注意容器启动先后的whoami输出以及终端提示符的变化)。

  • -ti 会进入容器的终端(使用ctrl-p+ctrl-q方式返回宿主机);
  • -name test 容器名以test命令,不指定会随机去一个字符串;
  • centos:latest 启动容器使用的镜像名;
  • /bin/bash 容器启动后的执行命令;

除了这里的几个启动参数外,启动容器还常用如下OPTIONS

  • --privileged=true 进入容器后,使用真正的root权限;
  • --net host 表示在容器内与主机共享网卡,host是安装Docker时在主机上建立的三个网络之一;
  • --volume host_dir:container_dir 把容器内的container_dir挂载到宿主机的host_dir目录;
  • --env 环境变量名=value 设置容器内的环境变量;
  • --cpu-shares n 设置容器占用CPU的权重n,这个权重是相对的,第一个容器是10,第二个是20,那第二个容器占用的CPU就是第一个的2倍;
  • -p host_port:container_port/udp 宿主机与容器的端口映射,默认是tcp,若是是udp须要/udp

(2) 容器基本操做

启动容器# docker run [OPTIONS] <image_name | image_id> [COMMAND] [ARG...]

查看容器信息: 使用inspect子命令查看容器/镜像的元数据。包括id启动命令网络链接方式端口映射等信息。

进入容器# docker exec -it <container_name | container_id>

中止容器# docker stop/kill <container_name | container_id>

删除容器# docker rm [-f] <container_name | container_id>

三、Dockerfile

虽然DockerHub提供了众多Linux镜像,但若是须要定制,DockerHub仍是不能知足的。这个时候就须要基于DockerHub提供的镜像作一些扩展。

Dockerfile

(1) 经常使用关键字

  • FROM 使用一个基础镜像构建;
  • RUN 执行一个shell命令,一般用来安装工具;
  • ENV 设置容器内的环境变量;
  • COPY 拷贝宿主机文件到镜像内;
  • ADD 拷贝宿主机文件到镜像内,并解压;
  • WORKDIR 设置容器启动时的工做目录,默认会cd到该目录,若是目录不存在会自动建立;

(2) 两个特殊的关键字

1. CMD

CMD指令容许用户指定容器启动的默认执行的命令。此命令会在容器启动且docker run没有指定其余命令时运行。

  • 若是docker run指定了其余启动命令,CMD指定的默认命令将被忽略;不然默认执行CMD指定的命令;
  • 若是Dockerfile中有多个CMD指令,只有最后一个CMD有效;

CMD的三种格式(不仅是CMD可使用,RUNENTRYPOINT也可使用这三种方式):

  1. /bin/bash -c的方法执行命令。好比CMD /bin/bash -c "echo hello world"
  2. 运行一个可执行文件并提供参数,称为Shell方式。好比CMD echo "hello world"
  3. 可执行文件连同参数经过一个数组提供,成为Exec方式,好比CMD ["echo", "hello world"]

1. ENTRYPOINT ENTRYPOINTCMD相似,都是指定容器的启动参数。不一样之处在于:

  • ENTRYPOINT必定会执行,不会被忽略;
  • CMD指令容许用户指定容器启动的默认执行的命令。此命令会在容器启动且docker run没有指定其余命令时运行;

ENTRYPOINT使用exec方式时,还能够经过使用CMD的exec方式提供额外的参数,此时CMD的参数列表仅包含参数、再也不有可执行文件。好比:

  • 下面的Dockerfile片断,ENTRYPOINT ["echo", "hello"] CMD ["world"],会输出hello world;
  • 若启动上面的Dockerfile建立的镜像,启动命令为docker run -it [image] cvte,会输出hello cvte

(3) 构建镜像

# docker build -t tag_name path_to_Dockerfile
复制代码

Tips: Dockerfile所在目录除了须要拷贝到镜像中的文件外,不要有其余无关文件或文件夹,即保证Dockerfile所在目录干净。不然构建时可能会出现长时间拷贝致使失败;

(4) 一个例子

Dockerfile仓库

四、Registry

Registry是存放Docker镜像的仓库,分公有和私有两种。

(1) DockerHub

DockerHubDocker公司对公众提供的免费Registry,用户能够在上面下载各类类型的应用或镜像。好比下载一个有Python3环境的镜像、能够提供redis存储服务的服务器。官网地址

(2) 公司内网

出于对速度或安全的考虑,用户能够建立本身私有的Registry。公司内网Registry地址

3、Docker管理

除了上面介绍的对容器和镜像的基本操做外,还可使用docker-compose管理容器。

docker-compose经过一个docker-compose.yml配置文件,完成单个容器的配置(好比镜像、端口映射、目录挂载、环境变量等)、多个相互依赖的容器编排(容器启动顺序)等功能。

这块内容较多而且也不难,有了上文的基础,经过下文的参考文档应该能掌握。

4、实现容器的底层技术

cgroupnamespace是实现容器的两个重要技术。cgroup实现资源限额namespace实现资源隔离

一、cgroup

  • 对容器的资源限制,好比--cpu-shares、-m实际就是在配置cgroup;
  • 在/sys/fs/cgroup/cpu/docker目录中,会为每一个容器建立一个cgroup目录,以容器长ID命名,里面的若干文件就是与CPU相关的cgroup配置。好比cpu.shares保存的就是--cpu-shares的配置;
  • 同理,/sys/fs/cgroup/memory/docker保存的就是容器内存的cgroup配置;

二、namespace

namespace相对cgroup要难一些。Linux使用了6中namespace,分别对应6种资源:Mount、UTS、IPC、PID、Network、User。

  • Mount namespace: 让容器看山去拥有整个文件系统,能够在容器内执行mount,这些操做只会在容器内生效;
  • UTS namespace:让容器拥有本身的hostname。默认状况下,容器的hostname是它的短ID,也可使用-h或--hostname指定。
  • IPC namespace:让容器拥有本身的IPC来实现进程间通讯,不会与主机的IPC混合在一块儿;
  • PID namespace:容器在宿主机上以进城的形式存在;全部容器进城都挂载dockerd进程下,同时也能够看到容易内只属于该容器的子进程;
  • Network namespace:让容器拥有本身独立的网卡、IP、路由等资源;
  • User namespace:让容器可以管理本身的用户,host不能看到容器中建立的用户。

参考文档: Docker--从入门到实践

相关文章
相关标签/搜索