前言
因为要搭环境复现漏洞等一系列原因,所以这里还是得把Docker学起来
介绍
by 菜鸟教程
Docker 是一个用于开发,交付和运行应用程序的开放平台。Docker 使您能够将应用程序与基础架构分开,从而可以快速交付软件。借助 Docker,您可以与管理应用程序相同的方式来管理基础架构。通过利用 Docker 的方法来快速交付,测试和部署代码,您可以大大减少编写代码和在生产环境中运行代码之间的延迟。
引用这里参考csdn文章的博主的理解:
1.可以快速搭建起程序运行所需要的环境。
2.可以打包程序和运行环境,避免因为缺乏某些库、或是环境变量设置的问题等导致程序无法运行。也就是说,解决了为什么在我的电脑上可以运行而在其他人电脑上不行的问题。
3.Docker只有需要的环境,比虚拟机占用的资源更少,操作也比虚拟机更简单。
安装
本人是在windows WSL2 上进行配置的
主要的安装流程可移步至菜鸟教程
这里提几个小tips
更改数据存储位置
windows默认安装在C盘,希望盘没逝
停止Docker服务
导出,备份数据到另一个文件夹
wsl --export docker-desktop-data "E:\Docker\docker-desktop-data.tar"
删除原有数据
wsl --unregister docker-desktop-data
更改数据存储盘并恢复数据
wsl --import docker-desktop-data "E:\Docker" "E:\Docker\docker-desktop-data.tar" --version 2
即将备份数据导入到新的虚拟盘,且指定虚拟盘的存放路径为E:\Docker,导入完成后在该目录下会存在一个ext4.vhdx的虚拟磁盘路径
然后直接启动docker就行
更改镜像源
经典切换国内镜像
在设置的Docker Engine添加以下内容
"registry-mirrors": [
"https://docker.mirrors.ustc.edu.cn",
"http://f1361db2.m.daocloud.io",
"https://registry.docker-cn.com"
],
"insecure-registries": [],
"debug": true,
"experimental": false
阿里云要注册账号,这里就不演示了(
运行
验证安装是否成功
cmd里执行命令
docker version
出现这些信息则说明安装完成
查看镜像
docker images
REPOSITY代表所在仓库,TAG表示该镜像标签(版本)
对应的Docker Desktop图形化界面
查看所有容器
docker ps -a
CONTAINER ID表示该容器在Docker中的唯一ID,稍后的相关操作可以使用该ID进行,IMAGES表示该容器使用的镜像,NAMES表示我们给当前容器起的花名,与ID一样是唯一的
对应的Docker Desktop图形化界面
从docker基础中可以了解到,docker容器其实就是拉取相应的镜像并启动它,那就可以理解成虚拟机,但与虚拟机相比优势更大,可以把这个容器便是一个基于Linux的独立的”操作系统”了
拉取镜像并启动容器
这里以hello-world镜像为例
拉取镜像
docker pull hello-world[:TAGS]
这样就算拉取成功了
对应的Docker Desktop图形化界面:
搜索栏中查找,点击Pull即可
接着可以使用
docker images
或者直接在Docker Desktop图形化界面中查看本机中所有的镜像最后启动一个容器实例
docker run -itd --name test hello-world /hello
返回了该容器的全称CONTAINER ID
其中
-itd
表示以交互式终端切后台运行的模式启动即启动后容器仅在后台运行,不会进入容器实例–name test
表示给该容器自定义的名字hello-world
表示使用的镜像/hello
对应执行的命令,交互式shell可以是/bin/bash
如果想进入该容器可以使用命令(如Ubuntu这类可以进入的镜像)
docker exec -it 【CONTAINER ID】 /bin/bash
注:在第三步执行的时候倘若还没有镜像则会自动拉取镜像
CONTAINER ID可以少几位,会自己识别
运行镜像
docker run hello-world
说明运行成功,这个方法会创建一个新的容器
基于CTF出题
记录了一次出题过程:
拉取镜像
先拉一个题目环境下来
这里拉了一个vaalacat/push_f12
下来
启动镜像
出题
先在本地编写题目代码
<!DOCTYPE html>
<html>
<head>
<title>FTwelve</title>
<!--flag{ctf web St@rt!}-->
</head>
<body>
<h1>这是什么?</h1>
<p>你说的对,但是web是由...</p>
<p>中间忘了</p>
<p>后面忘了</p>
<p>总之就是逐步发掘phpinfo()的真相(</p>
<!--Huh?-->
<?php
phpinfo();
?>
</body>
</html>
然后拷贝到容器中
docker cp ./ 35007d4:/var/www/html
封装镜像
把这个容器封装成一个新的镜像
docker commit 35007d my_f12
上传到自己的Hub
注册一个账号
然后
docker tag my_f12 c1oudfl0w0/my_f12:tags
然后就能push到自己的仓库了
实例
Docker上运行MongoDB
安装就不多说了
运行容器
docker run -itd --name mongo -p 27017:27017 mongo --auth
-p 27017:27017
:映射容器服务的27017端口到宿主机的27017端口。外部可以直接通过宿主机ip:27017 访问到 mongo 的服务--auth
:需要密码才能访问容器服务
添加用户(MongoDB > 6.0)
docker exec -it mongo mongosh admin
设置密码
db.createUser({ user:'admin',pwd:'123456',roles:[ { role:'userAdminAnyDatabase', db: 'admin'},"readWriteAnyDatabase"]});
尝试使用上面创建的用户信息进行连接
db.auth('admin', '123456')
调试
php
参考:https://depp.wang/2022/12/28/debug-docker-php-code-in-vscode/
PHP 容器中安装 xdebug 依赖
# 查看 xdebug 是否已安装 php -m | grep xdebug # 安装 pecl install xdebug # 开启 xdebug docker-php-ext-enable xdebug # 重启容器 docker restart <your-php-container-name>
修改 xdebug 配置
容器内 /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
zend_extension=xdebug xdebug.mode = debug xdebug.start_with_request = yes xdebug.client_port = 9003 xdebug.discover_client_host = true xdebug.client_host = host.docker.internal xdebug.remote_host = host.docker.internal
修改后重启容器
vscode配置
.vscode/launch.json
{ // Use IntelliSense to learn about possible attributes. // Hover to view descriptions of existing attributes. // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ { "name": "Listen for Xdebug", "type": "php", "request": "launch", "port": 9003, "pathMappings": { // 容器映射本地 "/data/project/material/": "${workspaceFolder}" // /data/project/material/ 路径是自己 PHP Docker 的 WorkingDir } } ] }
这里的mapping可以为多个文件之间的mapping,前面为容器中的地址后面为本地代码的地址
nodejs
参考:https://juejin.cn/s/debug%20node%20js%20docker%20container
在 Dockerfile 中使用
CMD ["node", "--inspect-brk", "app.js"]
命令,以启用 Node.js 的调试模式,并在代码中插入debugger
语句,以便在启动容器时自动停在调试器中断点处。使用
docker exec
命令连接到正在运行的容器,并使用 Node.js 调试器手动附加到正在运行的 Node.js 进程,例如:docker exec -it <container-id> node --inspect-brk=0.0.0.0:9229 app.js
,然后在 Chrome DevTools 中打开chrome://inspect
页面,并连接到正在运行的调试器。使用
docker-compose
配置文件启动容器,并在其中设置ports
和command
,以便在容器启动时自动启用 Node.js 调试器和调试模式,例如:version: '3' services: app: build: . ports: - "9229:9229" command: ["node", "--inspect-brk=0.0.0.0:9229", "app.js"]
python
参考:https://tttang.com/archive/1900/
Docker配置
方法一:vscode自动识别web框架
正常编写Docker文件即可,无需增加调试相关命令
方法二:通用远程调试
需要额外增加命令
- Dockerfile:
RUN pip install debugpy
- docker-compose.yml:(ports之后)
entrypoint: [ "python", "-m", "debugpy", "--listen", "0.0.0.0:5678", "--wait-for-client", "-m", "flask", "run", "-h", "0.0.0.0"]
,其中5678是vscode远程调试的端口
vscode调试配置
vscode 左侧调试栏->点击
新建调试文件
/或c+s+p->Debug: Start Debugging
选择
添加配置
主要以Django和flask框架为例(未加nodejs等),见0x131和0x132
方法一:vscode自动识别web框架
- 选择
python
->Docker: Python - Django/flask
- 会在工程目录下生成
.vscode
目录,其中包含两个json文件: - launch.json
{
// 使用 IntelliSense 了解相关属性。
// 悬停以查看现有属性的描述。
// 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
"configurations": [
{
"name": "Docker: Python - Django",
"type": "docker",
"request": "launch",
"preLaunchTask": "docker-run: debug",
"python": {
"pathMappings": [
{
"localRoot": "${workspaceFolder}/web",
"remoteRoot": "/usr/src"
}
],
"projectType": "django"
}
}
]
}
- tasks.json
{
"version": "2.0.0",
"tasks": [
{
"type": "docker-build",
"label": "docker-build",
"platform": "python",
"dockerBuild": {//自动生成,与docker文件保持一致
"tag": "",
"dockerfile": "${workspaceFolder}/Dockerfile",
"context": "${workspaceFolder}/[..]",
"pull": true
}
},
{
"type": "docker-run",
"label": "docker-run: debug",
"dependsOn":[
"docker-build"
],
"python": {
"args": [
"runserver",
"0.0.0.0:8000"
],
"file": "web/app.py" //程序主入口,需根据实际情况修改
}
}
]
}
注意:
- 这种情况vscode可能会修改Dockerfile,如果拿不准建议提前备份一下Docker配置
- 搭建github上的工程进行调试时,由于工程文件含requirements.txt,venv pip后实际调试失败,总报错:找不到依赖库
方法二:通用远程调试
- 选择
python
->Python: 远程附加
->输入调试端口,默认为5678 - 会在工程目录下生成
.vscode
目录,其中包含1个json文件: - lanch.json
{
// 使用 IntelliSense 了解相关属性。
// 悬停以查看现有属性的描述。
// 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Python: 远程附加",
"type": "python",
"request": "attach",
"connect": {
"host": "localhost",
"port": 5678 //远程调试端口
},
"pathMappings": [
{
"localRoot": "${workspaceFolder}",
"remoteRoot": "."
}
],
"justMyCode": true
}
]
}
- docker-compose.yml的ports添加一行:
- "5678:5678"
vscode调试
在待调试文件代码处下断点
运行docker:docker-compose.yml右键->Compose Up(第一次)或Compose Restart->等待docker正常启动
开始调试:
方法一:运行和调试->自动有
Python: Remote Attach
按钮,点击方法二:无
Python: Remote Attach
时,让待调试文件处于活跃状态(即当前看见的代码是调试代码)->运行和调试->齿轮右侧省略号->开始调试
java
参考:https://blog.csdn.net/haduwi/article/details/126296308
先在本地对应jar包的文件夹下启动idea,把jar包添加为库
接下来编辑运行配置
指定端口,命令行实参选择对应版本,然后复制这行实参到我们的docker启动执行命令中(我这里是docker-entrypoint.sh)
把运行指令改为
java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:6666 -jar /app/app.jar
/app/app.jar是我这里容器内的jar包路径
然后改docker-compose.yml,多设置一个端口
version: '3'
services:
web:
build: ../
environment:
# 仅为测试用flag
FLAG: "flag{a63b4d37-7681-4850-b6a7-0d7109febb19}"
ports:
# 设置了暴露端口
- 85:8080
- 6666:6666
restart: unless-stopped
接下来docker-compose up
启动docker
IDEA这里还要添加模块
第三方依赖的话需要把lib文件夹复制到项目根目录下,添加为库后才能跟进
然后就可以调试了