记一次Docker出题记录
前言
上学期新生赛前夕(2024.7.2~2024.10.1),我一直很苦恼怎样用docker出ctf-web题,我那时候有一个很错误的思维:我要先把docker学明白了,再去动手实践弄这些。
再加上我暑假以及开学后很长一段时间受一些事情干扰很重,那段时间有点摆大烂(别学我…)。然后我的题在新生赛上闹了个笑话:原本是一个文件包含题,直接在url中输入flag即可拿到。。
这次辅导员突然叫我们给自家专业搞个CTF小比赛,刚好练下我的docker技术。
这道题目出得很简单了,勿喷。。
About Docker
Docker到底是个啥,我从我个人的理解出发简单说说:
假设一个程序需要在A操作系统下配置B环境再加上C的依赖,如果没有docker,而且情况又不那么理想下:
我是B系统,我要现在虚拟机中整个A系统,再配环境配依赖七七八八的,特别特别麻烦。
但是docker的出现让我们能够把构建环境的一整个过程写在一个配置文件中(dockerfile),让docker把这个单独的环境给还原。这样就不必大炮打蚊子。而且方便传输。
几个重要的基础概念
dockerfile
Dockerfile 是一个文本文件,包含了构建 Docker 镜像所需的所有命令和指令。它是一个自动化的脚本,用来描述如何从基础镜像创建一个定制化的 Docker 镜像,并且执行一系列操作(例如安装软件、配置环境、复制文件等)。
常见的 Dockerfile 指令:
FROM
:指定基础镜像,例如FROM ubuntu:latest
。RUN
:在镜像中执行命令(例如安装软件包)。COPY
:将本地文件复制到镜像中。WORKDIR
:设置工作目录。CMD
或ENTRYPOINT
:指定容器启动时执行的命令。EXPOSE
:声明容器的端口。
示例 Dockerfile:
1 | dockerfile复制编辑# 使用官方的 Node.js 镜像作为基础镜像 |
docker-compose
Docker Compose 是一个用于定义和运行多容器 Docker 应用的工具。通过一个名为 docker-compose.yml
的配置文件,你可以使用 YAML 语法描述多个容器的服务、网络、卷等配置,并且一键启动和管理它们。
主要功能:
- 定义多个服务:你可以在同一个 Compose 文件中定义多个容器服务。
- 网络管理:自动创建和管理容器之间的网络连接。
- 数据卷:管理容器的数据卷,方便数据共享和持久化。
- 容器编排:通过一个命令启动或停止所有服务。
**示例 Docker Compose 文件 (docker-compose.yml
)**:
1 | yaml复制编辑version: '3' |
- 这个例子定义了两个服务:
web
使用nginx
镜像,暴露端口 8080。db
使用mysql
镜像,设置了数据库的 root 密码。
常用的 Docker Compose 命令:
docker-compose up
:根据配置文件启动所有服务。docker-compose down
:停止并移除服务。docker-compose build
:根据 Dockerfile 构建镜像。
实战
我想出一个文件包含+文件上传的简单CTF题。
首先新建一个目录,看看结构:
dockerfile
看看这些具体内容,就知道它在从上到下顺序构建docker环境。
1 | # 指定基础镜像为: |
在 Docker 中,镜像(image)是基于现有的操作系统构建的。对于你给出的 Dockerfile
,虽然它没有明确说明创建一个新的 Linux 系统,但 FROM php:7.3-fpm-alpine3.11
指定了基础镜像,而这个基础镜像就是包含了一个操作系统(在这个案例中是基于 Alpine Linux 的 PHP 镜像)。
docker-compose
这个就没什么好看的了:
1 | name: "upload" # 设置应用程序的名称 |
default.conf
nginx配置:
1 | server { |
基本内容看完了之后,直接在当前目录开命令行:
1 | docker-compose build |
记住每次修改docker配置文件,都要重新build
后台启动!
1 | docker-compose up -d |
调试
1 | docker exec -it upload Linux命令 |
这个命令可以查看当前docker-compose的运行情况。
push至dockerhub
这里我用的是命令行。
首先docker login
登录上dockerhub,注意这里如果登录不上的话,clash开全局代理。
然后docker images
查看所有镜像,关注到目标即可。
docker tag (image_id) userid/name:latest
注意这里的name在你的docker-compose里头看:
docker push user_id/name:latest
即可