Docker从入门到放弃

??为什么要学习 docker 呢?深有体会,由于一些原因只能在他人电脑上搭建环境,明明在自己电脑上的程序跑的好好的,在他人的电脑上就是死活出错。折磨人呀!!!!!可是能怎么办,工作还得继续,曲线救国呗,折腾了一天终于搞好了,那么以后呢?想到了之前搭建靶机时候用到的docker,时间长了也忘了,准备好好梳理学习入门一波。《十分感谢大神的文章,本文基于大神的文章学习整理。》

一、入门基础

?? Docker 使用 Google 公司推出的 Go 语言进行开发实现,基于 Linux 内核的 cgroup,namespace,以及 AUFS 类的 Union FS 等技术,对进程进行封装隔离,属于 操作系统层面的虚拟化技术。由于隔离的进程独立于宿主和其它的隔离的进程,因此也称其为容器。

Docker从入门到放弃

??热衷于 Ubuntu,后面的所有操作都是基于 Ubuntu的。

1. 基本概念

??Docker的三大组件:镜像、容器、仓库

1.1 镜像

??操作系统分为内核和用户空间,内核启动后会挂在root文件系统为用户控件提供支撑。

??Docker镜像就相当于一个root文件系统,但它是一个特殊的文件系统。提供了

(1)容器运行时所需的程序、库、资源、配置等文件,
(2)为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。

??镜像构建时,会一层层构建,前一层是后一层的基础。每一层构建完就不会再发生改变,后一层上的任何改变只发生在自己这一层。比如,删除前一层文件的操作,实际不是真的删除前一层的文件,而是仅在当前层标记为该文件已删除。

1.2 容器

??镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的 类 和 实例 一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。

??容器的实质是进程,容器进程运行于属于自己的命名空间。容器可以拥有自己的root文件系统、网络配置、进程空间、自己的用户ID空间,是在一个隔离的环境里。

1.3 仓库

??镜像构建完成后,可以很容易的在当前宿主机上运行,但是,如果需要在其它服务器上使用这个镜像,我们就需要一个集中的存储、分发镜像的服务,Docker Registry 就是这样的服务。一个 Docker Registry 中可以包含多个 仓库(Repository);每个仓库可以包含多个 标签(Tag);每个标签对应一个镜像。

??<仓库名>:<标签> 的格式来指定具体是这个软件哪个版本的镜像。仓库名经常以 两段式路径 形式出现,比如 jwilder/nginx-proxy。

仓库服务分类为:

Docker Registry 公开服务
私有 Docker Registry

2. Ubuntu安装Docker服务

# 将apt源使用https以确保软件下载过程中不被篡改,添加使用HTTPS传输的软件包以及CA证书
sudo apt-get install apt-transport-https ca-certificates curl software-properties-common

# 为确保下载软件包的合法性,需要添加软件源的GPG秘钥
curl -fsSL https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu/gpg | sudo apt-key add -

# 向 source.list 中添加 Docker软件源
sudo add-apt-repository     "deb [arch=amd64] https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu     $(lsb_release -cs)     stable"
    
# 更新Ubuntu源
sudo apt-get update


# 安装 Docker CE
sudo apt-get install docker-ce

# 使用脚本自动安装
curl -fsSL get.docker.com -o get-docker.sh
# 可以国内源进行安装
sudo sh get-docker.sh --mirror Aliyun

# 启动 Docker CE
sudo systemctl enable docker
sudo systemctl start docker

# 建立 docker 用户组
sudo groupadd docker
# 将当前用户加入到 docker组中
sudo usermod -aG docker $USER

# 关闭当前Terminal重新连接Ubuntu

# 测试Docker是否安装正确,执行命令,看到下面的输出就说明正确安装了
docker run hello-word


# 卸载旧版本的docker
sudo apt-get remove docker docker-engine docker.io

二、Docker使用

1. 镜像操作

1.1 获取镜像

从下载过程中,我们可以看到docker的镜像是由多层存储所构成的,下载也是一层层的下载,下载过程中给出了没一层的ID的前12位,并且下载结束后,给出该镜像完整的sha256的摘要,以确保下载一致性。

# 获取镜像格式
docker pull [选项] [Docker Registry 地址[:端口号]/]仓库名[:标签]
# 查看docker获取镜像帮助
docker pull --help
# 例如
docker pull ubuntu:18.04
# jenkins的下载过程
docker pull jenkins
Using default tag: latest
latest: Pulling from library/jenkins
55cbf04beb70: Pulling fs layer 
55cbf04beb70: Downloading [=========>                                         ]  8.289MB/45.31MB
9a8ea045c926: Pulling fs layer 
d4eee24d4dac: Downloading [============>                                      ]  12.71MB/50.06MB
c58988e753d7: Pulling fs layer 
d4eee24d4dac: Downloading [==========>                                        ]  10.68MB/50.06MB
70fcfa476f73: Download complete 
0539c80a02be: Downloading  6.405MB
54fefc6dcf80: Waiting 
911bc90e47a8: Waiting 
38430d93efed: Waiting 
7e46ccda148a: Waiting 
c0cbcb5ac747: Waiting 
35ade7a86a8e: Waiting 
aa433a6a56b1: Waiting 
841c1dd38d62: Waiting 
b865dcb08714: Waiting 
5a3779030005: Waiting 
12b47c68955c: Waiting 
1322ea3e7bfd: Waiting
# 下载安装完就会出现下面输出信息
Digest: sha256:eeb4850eb65f2d92500e421b430ed1ec58a7ac909e91f518926e02473904f668
Status: Downloaded newer image for jenkins:latest
docker.io/library/jenkins:latest

docker run的相关参数解释:

# docker启动Jenkins服务
sudo docker run -d -p 8099:8080 -v /opt/data/jenkins_home:/var/jenkins_home --name wjenkins jenkins:latest

docker run -it --rm ubuntu:18.04 bash
-it: -i,交互式操作;t,终端;
-rm:容器退出后随之将其删除,避免浪费空间
-d:是后台启用jenkins服务
-p:端口映射
--name:为容器命名
ubuntu:18.04:指用 ubuntu:18.04 镜像为基础来启动容器
bash:放在镜像后的是命令,可以创造一个交互式的shell
-v:挂载数据 /opt/data/jenkins_home:/var/jenkins_home   映射 jenkins_home到本地/opt/data/jenkins_home目录。例如启动jenkins的初始密码,秘钥库等都从这里面找

1.2 查看镜像

# 查看docker中全部的镜像
docker images
# 查看docker中部分的镜像
docker image ls jenkins
REPOSITORY(仓库名)  TAG(版本)          IMAGE ID(镜像ID)    CREATED(创建时间)   SIZE(所占用空间)
jenkins             latest              cd14cecfdb3a        17 months ago       696MB


# 镜像体积
# 查看镜像、容器、数据卷所占用的空间
docker system df
TYPE                TOTAL               ACTIVE              SIZE                RECLAIMABLE
Images              2                   1                   695.7MB             695.7MB (99%)
Containers          2                   0                   0B                  0B
Local Volumes       0                   0                   0B                  0B
Build Cache         0                   0                   0B                  0B


# 虚悬镜像(dangling image)--- 目前没看到,也没看到有什么用
# 查看虚悬镜像
docker image ls -f dangling=true
# 删除虚悬镜像
docker image prune


# 中间层镜像(为了加速镜像构建、重复利用资源,Docker 会利用 中间层镜像。所以在使用一段时间后,可能会看到一些依赖的中间层镜像)
docker image ls -a


# 以特定格式显示
docker image ls --format "{{.ID}}: {{.Repository}}"
fce289e99eb9: hello-world
cd14cecfdb3a: jenkins


# 以表格等距显示,并且有标题行
docker image ls --format "table {{.ID}}\t{{.Repository}}\t{{.Tag}}"
IMAGE ID            REPOSITORY          TAG
fce289e99eb9        hello-world         latest
cd14cecfdb3a        jenkins             latest
docker image ls 列表中的镜像体积总和并非是所有镜像实际硬盘消耗。由于 Docker 镜像是多层存储结构,并且可以继承、复用,因此不同镜像可能会因为使用相同的基础镜像,从而拥有共同的层。

1.3 删除镜像

# 删除镜像格式
docker image rm [选项] <镜像1> [<镜像2> ...]

# docker中存在的镜像
docker image ls
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
hello-world         latest              fce289e99eb9        12 months ago       1.84kB
jenkins             latest              cd14cecfdb3a        17 months ago       696MB

# 长ID删除
docker image rm fce289e99eb9
# 短ID删除,一般去长ID的前三位就能区分镜像
docker image rm fce


# 通过镜像名删除镜像
docker image rm hello-world


# 查看镜像摘要
docker image ls --digests
# 通过镜像摘要删除镜像
docker image rm :4fe721ccc2e8dc7362278a29dc660d833570ec2682f4e4194f4ee23e415e1064


# docker image ls 命令来配合删除
docker image rm $(docker image ls -q redis)

2. 容器操作

容器是独立运行的一个或一组应用,以及他们的运行态环境。

2.1 启动

启动容器的两种方式:

1.基于镜像新建一个容器并启动:docker run,该命令的标准操作
    (1)检查本地是否存在指定的镜像,不存在就从公有仓库下载
    (2)利用镜像创建并启动一个容器
    (3)分配一个文件系统,并在制度的镜像层外爱你挂载一层可读写层
    (4)从宿主主机配置的网桥接口中桥接一个虚拟接口到容器中去
    (5)从地址池配置一个IP地址给容器
    (6)执行用户指定的应用程序
    (7)执行完毕后容器被终止
2.在终止状态的容器重启启动:docker container start
# 新建并启动
# 用ubuntu输出打印
docker run ubuntu:18.04 /bin/echo "Hello Ubuntu"

# 启动一个bash终端,允许用户交互
docker run -t -i ubuntu /bin/bash


# 启动已终止容器
docker container start [容器的名称NAMES]

2.2 守护态进行

大多数是需要让docker在后台运行而不是直接把执行命令的结果输出在当前宿主机下。通过-d参数来实现。

# 不加-d参数运行容器,容器回吧输出的结果(STDOUT)打印到宿主机上
docker run ubuntu /bin/sh -c "while true; do echo hello world; sleep 1;done;"
hello world
hello world
hello world
...


# 加-d参数在后台运行
 docker run -d ubuntu /bin/sh -c "while true; do echo hello world; sleep 1;done;"
014d585a42f3974814e8d00d3be17b0babeda887456c8539e1922bc5d749368f


# 查看容器的信息docker container ls
docker container ls 
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
014d585a42f3        ubuntu              "/bin/sh -c ‘while t…"   52 seconds ago      Up 47 seconds                           zealous_gauss



# 查看容器后台打印的日志信息docker container logs [docker container -d后的那个ID]
docker container logs 014d585a42f3974814e8d00d3be17b0babeda887456c8539e1922bc5d749368f
hello world
hello world
hello world
...

2.3 终止

# 查看容器的运行状态
docker container ls -a

# 终止一个运行中的容器
docker container stop [ID]

# 启动一个容器
docker container start [容器的名称NAMES]

# 重新启动一个容器
docker container restart [容器的名称NAMES]

2.4 进入容器

使用-d参数,容器启动后会进入后台。那么怎么进入容器操作呢?

docker attch [ID或ID的前三位:docker container ls出的]
    exit 退出的时候回导致容器停止
docker exec(推荐使用)
    -i -t: 可以使用熟悉的 Linux命令提示符
    exit 退出的时候不会使容器退出
# 后台交互式启动ubuntu
docker run -dit ubuntu
5f7cbebeb2b97f8ac8de6a8b79e196dcd7583a37435781ef6669e9237ad9f39d


# 查看容器的运行
docker container ls
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
5f7cbebeb2b9        ubuntu              "/bin/bash"         39 seconds ago      Up 34 seconds                           hopeful_spence


# docker exec 进入容器
 docker exec -it 5f7 bash
:/# 

# docker attach J进入容器
docker attach 57f bash

2.5 导出和导入

# 导出容器 docker export
 docker container ls -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                         PORTS               NAMES
5f7cbebeb2b9        ubuntu              "/bin/bash"              3 minutes ago       Up 3 minutes                                       hopeful_spence
docker export 5f7cbebeb2b9 > ubuntu.tar


# 导入容器快照docker import
cat ubuntu.tar | docker import - test/ubuntu:v1.0
sha256:e27783b11623f2f56137ab8469963296d14545aac6607febe5e7d4c83a92c6f3
# 通过执行的URL或者某个目录来导入
docker import http://example.com/exampleimage.tgz example/imagerepo
# 查看导入的容器
docker image ls
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
test/ubuntu         v1.0                e27783b11623        10 seconds ago      64.2MB

2.6 删除

# 删除容器 docker container rm [容器的名字:通过docker contaniner ls 可以查看]
:~$ docker container ls
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
5f7cbebeb2b9        ubuntu              "/bin/bash"         9 minutes ago       Up 9 minutes                            hopeful_spence
:~$ docker container rm hopeful_spence
Error response from daemon: You cannot remove a running container 5f7cbebeb2b97f8ac8de6a8b79e196dcd7583a37435781ef6669e9237ad9f39d. Stop the container before attempting removal or force remove
:~$ docker container stop hopeful_spence
hopeful_spence
:~$ docker container rm hopeful_spence
hopeful_spence


# 清理所有处于终止状态的容器 docker container prune
# 用 docker container ls -a 命令可以查看所有已经创建的包括终止状态的容器
:~$ docker container ls -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                         PORTS               NAMES
014d585a42f3        ubuntu              "/bin/sh -c ‘while t…"   About an hour ago   Exited (0) 17 minutes ago                          zealous_gauss
28ceff128046        ubuntu              "/bin/sh -c ‘while t…"   About an hour ago   Exited (0) About an hour ago                       cocky_bohr
9ae9bef2e2d5        ubuntu              "/bin/bash"              About an hour ago   Exited (0) About an hour ago                       trusting_tereshkova
978423cea835        ubuntu              "/bin/echo ‘Hello Ub…"   2 hours ago         Exited (0) 2 hours ago                             angry_bose
0a73192e9dfd        hello-world         "/hello"                 2 hours ago         Exited (0) 2 hours ago                             eloquent_wilbur
81f60b6062e3        hello-world         "/hello"                 26 hours ago        Exited (0) 26 hours ago                            elegant_almeida
d9d4d77cbf25        hello-world         "/hello"                 2 days ago          Exited (0) 2 days ago                              condescending_easley
:~$ docker container prune
WARNING! This will remove all stopped containers.
Are you sure you want to continue? [y/N] y
Deleted Containers:
014d585a42f3974814e8d00d3be17b0babeda887456c8539e1922bc5d749368f
28ceff12804603c73d3516654b0b915a909053268529855e234d58ca7567663b
9ae9bef2e2d56680a2056a7853fee9b87eb90186db9ff44823030f3266faf0b6
978423cea83542f1120f8c27451107c2a00df48becbc2e99a62da977acd899f9
0a73192e9dfdd6f4969cf50286fcd3bc36a6e00f2a14822d73dd85f62749c616
81f60b6062e394ab3dc3e6e560e17522472a84cccf768865f88652b02af4a7d4
d9d4d77cbf258ffcb2bf5d6375284bd303517bc3c5e69c60a17a29592023d439

Total reclaimed space: 12B
:~$ docker container ls -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

3.访问仓库

仓库是集中存放镜像的地方。

3.1 Docker Hub

1.注册官方的docker账号:https://hub.docker.com

2.登录docker login; 退出docker logout

3.拉取镜像:docker search ubuntu

4.拉取镜像:docker pull ubuntu

5.推送镜像:docker push 自己的镜像

docker tag ubuntu:18.04 username/ubuntu:18.04

docker image ls

docker push username/ubuntu:18.04

docker search username

3.2 私有仓库

docker-register是官方提供的工具,可以用于构建私有的镜像仓库。

# 获取官方register镜像来运行
docker run -d -p 5000:5000 --restart=always --name registry registry

# 启动私有仓库
# -v参数来将镜像文件存在本地的指定路径
docker run -d -p 5000:5000 -v /opt/data/registry:/var/lib/registry registry

# 然后和共有仓的操作就一样了

# 但是Registry 创建的仓库面临一些维护问题。比如某些镜像删除以后空间默认是不会回收的,需要一些命令去回收空间然后重启 Registry 程序。Nexus可以很好解决这个问题
# 启动 Nexus 容器
# 第一次启动 Nexus 的默认帐号是 admin 密码是 admin123 登录以后点击页面上方的齿轮按钮进行设置
docker run -d --name nexus3 --restart=always     -p 8081:8081     --mount src=nexus-data,target=/nexus-data     sonatype/nexus3

4.数据管理

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

数据卷
挂在主机目录

Docker从入门到放弃

4.1 数据卷

4.2 挂在主机目录

5.使用网络

Docker允许通过外部访问容器或容器互联的方式提供网络服务。

5.1 外部访问容器

通过 -P 或 -p 参数来指定端口映射,Docker会随机映射一个49000~49900的端口到内部容器开放的网络端口。

docker run -d -p tranining/webapp python app.py

# 查看容器的端口映射
docker container ls -l
# 查看应用信息
docker logs -f nostalgic_morse


# 映射所有接口地址(使用 hostPort:containerPort 格式本地的 5000 端口映射到容器的 5000 端口)
docker run -d -p 5000:5000 training/webapp python app.py


# 映射到指定地址的指定接口(可以使用 ip:hostPort:containerPort 格式指定映射使用一个特定地址)
docker run -d -p 127.0.0.1:5000:5000 training/webapp python app.py

# 映射到指定地址的任意端口(使用 ip::containerPort 绑定 localhost 的任意端口到容器的 5000 端口,本地主机会自动分配一个端口)
docker run -d -p 127.0.0.1::5000 training/webapp python app.py

# 查看映射端口配置
docker port nostalgic_morse[容器名称] 5000

5.2 容器互联

强烈建议将容器加入自定义的Docker网络开连接多个容器

# 新建网络my-net
docker run -it --rm --name busybox1 --network my-net busybox sh
# 运行容器并加入到my-net网络中
docker run -it --rm --name busybox2 --network my-net busybox sh
# 查看容器信息
docker container ls
# ping 来证明 busybox1 容器和 busybox2 容器建立了互联关系,分别在容器中去ping对方

5.3 配置DNS

6. Kubernetes

Kubernetes是一个开源的,用于管理云平台中多个主机上的容器化的应用,Kubernetes的目标是让部署容器化的应用简单并且高效(powerful),Kubernetes提供了应用部署,规划,更新,维护的一种机制。

听过一个演讲课,目前行业中流行的是K8S+Docker架构。

7.靶机搭建(Docker实战)

学习转载pageuo的FreeBuf.com文章】,谢谢大佬的分享。

项目实际中为了验证扫描器的扫描准确性和扫描器的性能,由于长期扫描国外开源的扫描靶机会被封禁IP,影响扫描结果。为了项目的可持续性,想到了自己来搭建靶场验证扫描器的功能和性能。感谢pageuo大佬的靶机搭建经验。

7.1 搭建Vulhub

Vulhub是由 Phithon 维护的一款面向大众的开源漏洞靶场,只需要根据命令编译、运行就可搭建一个完整的漏洞靶场镜像。

# 配置docker基础环境
# 安装pip
curl -shttps://bootstrap.pypa.io/get-pip.py | python3
# 安装docker
sudo apt-get update && apt-get install docker.io
# 启动docker服务
sudo service docker start
# 安装compose
pip install docker-compose

# 拉取编译运行靶机
# 拉取vulhub
git clone :phith0n/vulhub.git
# 在线编译docker环境
cd vulhub/struts/s2-016
docker-compose build
# 启动靶机
docker-compose up -d

7.2 搭建Vulapp

Vulapp手机各种漏洞环境,统一采用Dockerfile进行管理,同事也手机了安全工具环境。

# 拉取Vulapp
git clone :Medicean/VulApps.git