Docker从入门到放弃
??为什么要学习 docker 呢?深有体会,由于一些原因只能在他人电脑上搭建环境,明明在自己电脑上的程序跑的好好的,在他人的电脑上就是死活出错。折磨人呀!!!!!可是能怎么办,工作还得继续,曲线救国呗,折腾了一天终于搞好了,那么以后呢?想到了之前搭建靶机时候用到的docker,时间长了也忘了,准备好好梳理学习入门一波。《十分感谢大神的文章,本文基于大神的文章学习整理。》
一、入门基础
?? Docker 使用 Google 公司推出的 Go 语言进行开发实现,基于 Linux 内核的 cgroup,namespace,以及 AUFS 类的 Union FS 等技术,对进程进行封装隔离,属于 操作系统层面的虚拟化技术。由于隔离的进程独立于宿主和其它的隔离的进程,因此也称其为容器。
??热衷于 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.数据管理
在容器中管理数据主要有两种方式:
数据卷 挂在主机目录
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