从零开始的 Docker 使用教程

分类:Linux 评论: 0

Docker 是一个开源的应用容器引擎,基于 Go 语言开发 遵从 Apache 2.0 协议开源。

Docker 可以让用户打包应用以及依赖到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。Docker 是一个横跨 IaaS 和 PaaS 层的项目。

Docker 起源于 2010 年创业的一家叫作 dotCloud 的美国公司,dotCloud 早期是基于LXC技术的 PaaS 平台,它的理念是提供跨底层 IaaS 云、支持多种开发语言的开发云平台。但随着越来越多的公有云服务商进入,dotCloud 的理念很难依靠一家公司专有的技术实现。于是 dotCloud 的创始人在 LXC 的基础上,对容器技术进行了简化和标准化,命名为 Docker。

2013年3月,因 PaaS 市场发展缓慢,创始人 Solomon Hykes 决定放手一搏,将 Docker 项目开源同时推出了开放容器项目(OCP),Docker 和 Docker 开源社区随后迅速火起来。

2013 年 10 月 29 日,dotCloud 公司更名为 Docker 公司。目前,Docker已经成为发展最快的容器技术。

Docker 将软件所需的依赖及程序本体构建为一个独立镜像,可以在任何部署了 Docker 的 Linux 服务器上运行,减轻了运维人员的部署难度及跨系统的依赖问题。

容器与虚拟化

容器与虚拟化不同,容器使用完全沙箱机制,容器与容器相互之间不会有任何影响,更重要的是容器的性能开销极低。简单可以理解为容器是在隔离的环境运行的一个进程,如果进程被停止,容器就会销毁。

而虚拟化则需要一定的硬件支持,比如 KVM 虚拟化只能基于 Linux 内核(对版本有一定要求)进行虚拟化。并且虚拟化是完整虚拟化,会虚拟化出完整的一套系统,因此启动虚拟机需要走一遍完整的系统启动流程,消耗的时间比较久(相对于容器来说)。

容器的特性

容器的发展

UNIX Chroot(change root,切换根目录)这项功能将Root目录及其它子目录变更至文件系统内的新位置,且只接受特定进程的访问,即可构建一个简易的子系统。其设计目的在于为每个进程提供一套隔离化磁盘空间。1982 年其被添加至BSD。

FreeBSD Jails 与 Chroot 的定位类似,不过其中包含有进程沙箱机制以对文件系统、用户及网络等资源进行隔离。通过这种方式,它能够为每个 Jail、定制化软件安装包乃至配置方案等提供一个对应的IP地址。Jails 技术为 FreeBSD 系统提供了一种简单的安全隔离机制。它的不足在于这种简单性的隔离也同时会影响 Jails 中应用访问系统资源的灵活性。

Solaris Zone 技术为应用程序创建了虚拟的一层,让应用在隔离的 Zone (空间)中运行,并实现有效的资源管理。每一个 Zone 拥有自己的文件系统,进程空间,防火墙,网络配置等。Solaris Zone 技术真正的引入了容器资源管理的概念。在应用部署的时候为 Zone 配置一定的资源,在运行中可以根据 Zone 的负载动态修改这个资源限制并且是实时生效的,在其他Zone不需要资源的时候,资源会自动切换给需要的资源的Zone,这种切换是即时的不需要人工干预的,最大化资源的利用率,在必要的情况下,也可以为单个 Zone 隔离一定的资源。

LXC (Linux Containers,Linux 容器),其通过 cgroups 以及 Linux Namespaces 实现。也是第一套完整的 Linux 容器管理实现方案。在 LXC 出现之前,Linux 上已经有了类似 Linux-Vserver 、OpenVZ 和 FreeVPS。虽然这些技术都已经成熟,但是这些解决方案还没有将容器支持集成到主流 Linux 内核。相较于其它容器技术,LXC 能够在无需任何额外补丁的前提下运行在原版 Linux 内核之上。目前 LXC 项目由 Canonical 有限公司负责赞助及托管。

Docker 项目最初是由一家名为 DotCloud 的平台即服务厂商所打造,其后该公司更名为Docker。Docker在起步阶段使用 LXC,而后利用自己的 Libcontainer 库将其替换下来。与其它容器平台不同,Docker引入了一整套与容器管理相关的生态系统。其中包括一套高效的分层式容器镜像模型、一套全局及本地容器注册表、一个精简化REST API以及一套命令行界面等等。

Docker 入门

安装 Docker

本文环境为 CentOS 7 ,部署 Docker 需要先安装 EPEL 源。

# yum install epel-release -y

从清华源获取 REPO 文件

# wget -O /etc/yum.repos.d/docker-ce.repo https://mirrors.ustc.edu.cn/docker-ce/linux/centos/docker-ce.repo

替换源地址为国内源(大陆使用可提速及提高稳定性)

# sed -i 's#download.docker.com#mirrors.tuna.tsinghua.edu.cn/docker-ce#g' /etc/yum.repos.d/docker-ce.repo

安装 Docker CE (社区版)

# yum install docker-ce -y

优化镜像拉取地址

# cat >> /etc/docker/daemon.json <<'EOF'
{
  "registry-mirrors": ["https://registry.docker-cn.com"]
}
EOF

官方部署方法

此部分教程为额外内容,若主机是国外主机,请使用此方式部署,国内主机对此源的连通性较差,推荐使用上方的国内源进行部署。

配置依赖

$ sudo yum install -y yum-utils \
  device-mapper-persistent-data \
  lvm2

添加仓库

$ sudo yum-config-manager \
    --add-repo \
    https://download.docker.com/linux/centos/docker-ce.repo

其他选项

test 为测试分支,edge 为先锋分支(最新特性)。

$ sudo yum-config-manager --enable docker-ce-edge
$ sudo yum-config-manager --enable docker-ce-test

安装社区版

$ sudo yum install docker-ce

小贴士:仅推荐开发及测试环境使用 edge 及 test 分支。

Docker 命令

执行 docker 命令前需要将 docker 启动,否则会报错,因为 docker 也是一个标准的 C/S 架构。

# systemctl enable docker
# systemctl start docker

基础命令

检查 Docker 版本信息,会列出引擎的详细信息。

[root@docker01 ~]# docker version
Client:
 Version:           18.09.0
 API version:       1.39
 Go version:        go1.10.4
 Git commit:        4d60db4
 Built:             Wed Nov  7 00:48:22 2018
 OS/Arch:           linux/amd64
 Experimental:      false

Server: Docker Engine - Community
 Engine:
  Version:          18.09.0
  API version:      1.39 (minimum version 1.12)
  Go version:       go1.10.4
  Git commit:       4d60db4
  Built:            Wed Nov  7 00:19:08 2018
  OS/Arch:          linux/amd64
  Experimental:     false

检查 Docker 信息

[root@docker01 ~]# docker info
Containers: 0
 Running: 0
 Paused: 0
 Stopped: 0
Images: 4
Server Version: 18.09.0
Storage Driver: overlay2
 Backing Filesystem: xfs
 Supports d_type: true
 Native Overlay Diff: true
Logging Driver: json-file
Cgroup Driver: cgroupfs
Plugins:
 Volume: local
 Network: bridge host macvlan null overlay
 Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog
Swarm: inactive
Runtimes: runc
Default Runtime: runc
Init Binary: docker-init
containerd version: c4446665cb9c30056f4998ed953e6d4ff22c7c39
runc version: 4fc53a81fb7c994640722ac585fa9ca548971871
init version: fec3683
Security Options:
 seccomp
  Profile: default
Kernel Version: 3.10.0-862.14.4.el7.x86_64
Operating System: CentOS Linux 7 (Core)
OSType: linux
Architecture: x86_64
CPUs: 1
Total Memory: 1.936GiB
Name: docker01
ID: NIDN:RIAL:XLUR:DUQP:FQSQ:BNBI:KHXJ:5ELK:3DA6:NHN4:2AZC:66AI
Docker Root Dir: /var/lib/docker
Debug Mode (client): false
Debug Mode (server): false
Registry: https://index.docker.io/v1/
Labels:
Experimental: false
Insecure Registries:
 127.0.0.0/8
Live Restore Enabled: false
Product License: Community Engine

小贴士:此命令会展示出 docker 详细的信息,包括镜像数量及启动的容器信息等,因此一般用于监控使用。

镜像相关命令

# docker image search    检索镜像
# docker image pull      拉取镜像
# docker image ls        镜像列表
# docker image save      导出镜像
# docker image load      导入镜像
# docker image rm        删除镜像
# docker image inspect   镜像信息
# docker image build     构建镜像

容器相关命令

# docker container run             运行容器
# docker container ps              容器列表
# docker container exec            进入容器
# docker container stop            停止容器
# docker container kill            杀死容器
# docker container start           启动容器
# docker container rm              删除容器
# docker container inspect         容器信息
# docker container update          更新容器

Docker 实例

拉取一个镜像

# docker image pull centos:6.9

使用此命令即可从仓库拉取某个版本的 centos 镜像,若省略冒号及后面的版本号则默认拉取最新版 latest 。

拉取一个 NGINX 镜像

# docker image pull nginx

启动第一个容器

# docker run -d -p 80:80 nginx

小贴士: -d 放在后台 -p 端口映射,冒号分割外部内部端口,最后指定镜像的名。

容器的镜像管理

# docker search IMAGE_NAME

小贴士:IMAGE_NAME 替换为需要搜索的镜像名,选择镜像的原则,有官方优先官方,其次考虑星星(点赞)多的。

已存在的镜像列表

# docker image list

或者可以使用(推荐)

# docker images

删除已存在的镜像

# docker image rm

或者可以使用(推荐)

# docker rmi

导出本地的镜像

# docker image save centos > docker_centos.tar.gz

小贴士:docker image save 可以简写为 docker save

导入本地镜像

# docker image load -i docker_centos.tar.gz

容器运行参数

# docker container run -it --name centos6 centos:6.9 /bin/bash

小贴士: -it 分配交互式终端,--name 指定容器名字,/bin/bash 指定命令解析器覆盖初始命令,部分镜像的基础镜像为精简镜像,因此请使用 /bin/sh

docker run 命令等同于创建容器实例并启动(docker create + docker start)

停止容器

# docker container stop CONTAINER_ID

杀死容器(强制)

# docker container kill CONTAINER_ID

容器列表

# docker container ps

小贴士:在此容器系列的命令中,中间的 container 可以省略,之后的全部命令会默认省略 container。此命令仅会显示存活的容器,添加-a参数即可显示全部的容器(包括已经退出的容器)。

即:

# docker ps -a

小贴士:其他有实际作用的参数还有 -q 仅显示容器 ID。

进入容器(大部分情况下为了排错)

# docker exec -it CONTAINER_ID /bin/bash

小贴士:使用 -it 分配交互式终端,CONTAINER_ID 可以使用 ID 或者 NAME,最后指定命令解释器。

# docker attach CONTAINER_ID

小贴士:此命令会共享同一个终端,因此不推荐使用。

注意:进入容器后不可使用 CTRL+D 退出或者输入 exit 命令进行退出,会导致容器退出,请使用 CTRL+P+Q 进行容器挂起。

删除容器

# docker rm -f CONTAINER_ID

小贴士:-f 参数为 force 为强制删除,可以移除失去响应的容器。

删除全部容器

# docker rm -f `docker ps -a -q`

总结:容器内的第一个进程必须一直处于前台运行的状态(必须 HANG 住),否则这个容器执行完毕命令就会处于退出状态(瞬间完成并退出)!

容器的网络访问

# docker container run -d -p 80:80 nginx

小贴士:容器的网络是建立在容器内部的,类似于沙箱,因此容器想对外开放端口需要对外进行映射,映射使用的是 NAT (iptables)方式,-P 为随机映射。

容器的数据卷管理

# docker container run -d -p 80:80 -v /opt/html:/var/www/html nginx

数据卷(文件或目录)

    -v /data
    -v src(宿主机的目录):dst(容器的目录)

数据卷容器

    --volumes-from

将容器保存为本地镜像

# docker commit CONTAINER_ID/CONTAINER_NAME   CONTAINER_NEW_NAME[:VERSION]

更新容器设置

# docker update --restart=always CONTAINER_ID

小贴士:若建立容器时忘记添加参数可以使用此种方式进行更新。

例子

1)基于容器制作镜像

# docker run -it centos:6.9

2)进入容器进行操作

yum install httpd
yum install openssh-server
/etc/init.d/sshd start

cat >> init.sh <<'EOF'
#!/bin/bash
/etc/init.d/httpd start
/usr/sbin/sshd -D
EOF

chmod +x /init.sh

3)查看容器的ID

# docker container ls -a

4)将容器提交为镜像

# docker commit CONTAINER_ID centos6-ssh-httpd:v1

5)测试镜像功能

扩展

说到 SystemD ,这个套件已经成为主流 Linux 发行版(比如 CentOS 7、Ubuntu 14+)默认的服务管理,取代了传统的 SystemV 服务管理。SystemD 维护系统服务程序,它需要特权去会访问 Linux 内核。而容器并不是一个完整的操作系统,只有一个文件系统,而且默认启动只是普通用户这样的权限访问 Linux 内核,也就是没有特权,所以自然就用不了!

因此,请遵守容器设计原则,一个容器里运行一个前台服务!

以特权模式运行容器即可解决此问题。

创建容器:

# docker run -d -name centos7 --privileged=true centos /usr/sbin/init

进入容器:

# docker exec -it centos /bin/bash

即可使用 systemD 启动服务

# yum install chrony
# systemctl start chronyd

Docker 构建镜像

Dockerfile 主要组成部分:

    FROM:centos:6.9    基础镜像信息        
    RUN yum install openssh-server -y    镜像操作指令
    CMD ["/bin/bash"]    容器启动执行指令

Dockerfile 常用指令:

    FROM 指定基础镜像
    MAINTAINER 指定维护者信息,可选
    RUN 在命令前面加上RUN即可
    ADD COPY文件,会自动解压
    WORKDIR 设置当前工作目录
    VOLUME 设置卷,挂载主机目录
    EXPOSE 指定对外的端口(-P 随机端口)
    CMD 指定容器启动后的要干的事情(可被替换)

Dockerfile 其他指令:

    COPY        复制文件
    ENV         环境变量
    ENTRYPOINT  容器启动后执行的命令(无法被替换,启容器的时候指定的命令,会被当成参数)

Docker 镜像层级

容器的镜像并不是一个单纯的文件而是一个多层覆盖后的层级文件,如图例所示。

Docker 自建镜像仓库

因此众所周知的原因,官方的仓库在中国大陆下载速度很慢甚至可能失败。并且企业及个人可能有打包完的自建镜像,因此需要自建仓库进行托管,不仅可以提高下载速度还能给企业或个人提供一个私人仓库。

搭建普通的仓库(无验证)

启动一个名为 registry 镜像

# docker run -d -p 5000:5000 --restart=always --name registry -v /opt/myregistry:/var/lib/registry  registry
# docker pull busybox
10.0.0.11:5000/centos6-sshd:v3
# vi /etc/docker/daemon.json
{
  "registry-mirrors": ["https://registry.docker-cn.com"],
  "insecure-registries": ["10.0.0.11:5000"]
}
# systemctl restart docker
docker push 10.0.0.11:5000/centos6-sshd:v3

带认证的仓库

# yum install httpd-tools -y
# mkdir /opt/registry-var/auth/ -p
# htpasswd  -Bbn kane material  >> /opt/registry-var/auth/htpasswd
# docker run -d -p 5000:5000 --restart=always --name registry -v /opt/registry-var/auth/:/auth/ -v /opt/myregistry:/var/lib/registry -e "REGISTRY_AUTH=htpasswd" -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd registry 

参考链接

回复