> For AI agents: the complete documentation index is available at /llms.txt, the full documentation bundle is available at /llms-full.txt.

# Use Docker and K8s

Here we use the lightweight K3s as an example. If you have already deployed a K8s cluster, you can refer to the subsequent configuration for similar settings.

:::danger

**Please read the entire tutorial before proceeding, otherwise the deployment result may not meet expectations.**

:::

## Install Docker

You can find the installation instructions on the [Docker official website](https://docs.docker.com/engine/install/), and use the basic configuration in [Quick Start](/guide/start/quick-start.md) to run GZCTF.

## Install K3s

K3s is a lightweight k8s distribution that can be quickly deployed on single and multiple machines. Official documentation: [https://docs.k3s.io/](https://docs.k3s.io/)

:::warning If you only have one machine?

If you only have one machine, we strongly recommend using other methods for deployment:

- For **private intranet competitions with fewer than 200 teams and 30 challenges**, you can directly use Docker for deployment without using k8s.
- For **public or larger competitions**, it is strongly recommended to use k3s for integrated deployment, **do not use Docker**.

***

Finally, if you really want to run k3s through Docker, you can specify the Docker backend by adding the following parameters during installation, **we strongly do NOT recommend you to do this**, you may need to fix various compatibility issues and cause a lot of trouble.

```bash
INSTALL_K3S_EXEC="--docker"
```

:::

:::info

If you need to run more than 255 challenge containers on a single k3s instance, you **need to specify `INSTALL_K3S_EXEC` during k3s installation** and change `node-cidr-mask-size` to the desired subnet size.

```bash
INSTALL_K3S_EXEC="--kube-controller-manager-arg=node-cidr-mask-size=22"
```

**The above configuration cannot be easily changed after installation.** We recommend using `/22` (about 1024 Pods per node), or `/20` (about 4096 Pods per node) if needed. Increasing the block further (e.g., `/16`) just reserves an oversized address space per node and reduces the cluster's ability to scale out workers.

The above configuration only changes the IP address range used by the node Pods. If you need to change the node's Pod limit, please refer to the following.

:::

And install k3s in the following way. For more information, please refer to [k3s installation configuration](https://docs.k3s.io/installation/configuration):

```bash
curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC="..." sh -
```

:::info

Chinese users can use a mirror site to speed up installation.

```bash
curl -sfL https://rancher-mirror.rancher.cn/k3s/k3s-install.sh | INSTALL_K3S_MIRROR=cn sh -
```

:::

For multi-node installation and cluster setup, please refer to the [official documentation](https://docs.k3s.io/en/quick-start).

## Configure GZCTF

The connection configuration file for k3s is located at `/etc/rancher/k3s/k3s.yaml`, and it can be exported using the following command:

```bash
sudo cat /etc/rancher/k3s/k3s.yaml
```

Use the following command to obtain the IP address of the k3s control-panel machine:

```bash
sudo k3s kubectl cluster-info
```

:::info

If it shows `127.0.0.1`, it means that the k3s control-panel is on the current machine. Please use `ip a` to check the IP address of the current machine.

You can directly use the IP address or use a domain name, but make sure the domain name resolves to the machine where the k3s control-panel is located, and ensure that the machine running GZCTF can access port 6443 on it.

:::

Save the above output as `kube-config.yaml` and change the `server` field to the IP address of the machine where the k3s control-panel is located, for example:

```yaml
apiVersion: v1
clusters:
  - cluster:
      certificate-authority-data: # ...
      server: https://127.0.0.1:6443 # change this to your k3s control-panel's IP or domain
    name: default
# ...
```

Save it to the machine where GZCTF is deployed, in the same folder as `compose.yml`, for example, `kube-config.yaml`.
Then modify the mount configuration in `compose.yml`:

```yaml
gzctf:
  image: gztime/gzctf:latest
  restart: always
  ports:
    - "80:8080"
  networks:
    default:
  volumes:
    - "./data/files:/app/files"
    - "./appsettings.json:/app/appsettings.json:ro"
    - "./kube-config.yaml:/app/kube-config.yaml:ro" # this is required for k8s deployment
    # - "/var/run/docker.sock:/var/run/docker.sock" # this is required for docker deployment
  depends_on:
    - db
```

Also, change the `appsettings.json` file and set the `ContainerProvider` field:

```json
{
  "Type": "Kubernetes",
  "PublicEntry": "ctf.example.com" // change this to your k3s control-panel's IP or domain
}
```

Restart GZCTF, and then you can use k3s as the container backend. Users who have already used k8s can also refer to the above configuration process to integrate GZCTF into an existing k8s cluster.

## Change NodePort Port Range

The default NodePort port range for k3s is 30000-32767, which may not meet your requirements. Therefore, you can modify the NodePort port range of k3s according to your needs.

Run the following commands on the machine where the k3s control-panel is located:

- `sudo nano /etc/systemd/system/k3s.service`

- Edit the `ExecStart` setting below to specify `service-node-port-range`

  ```bash
  ExecStart=/usr/local/bin/k3s \
      server \
      --kube-apiserver-arg=service-node-port-range=20000-50000
  ```

- `sudo systemctl daemon-reload`

- `sudo systemctl restart k3s`

## Change the container limit of K3s

The default container limit of K3s is 110, which may not be suitable for a large number of small containers in a competition. Therefore, you can change the container limit of K3s according to your needs.

:::info

Reference: [How do you increase maximum pods per node in K3S?](https://stackoverflow.com/questions/65894616/how-do-you-increase-maximum-pods-per-node-in-k3s)

:::

On the machine where the k3s control-panel is located, use the built-in config file `/etc/rancher/k3s/config.yaml`:

- `sudo nano /etc/rancher/k3s/config.yaml`

- Add or update the following (example increases per-node limit to 800):

  ```yaml
  kubelet-arg:
    - max-pods=800
  ```

- Restart the service to apply:

  ```bash
  sudo systemctl restart k3s
  ```

- Optional: If you also need a larger Pod subnet per node, configure `kube-controller-manager-arg` in the same file. We recommend `/22` (\~1024 Pods/node), or `/20` if required:

  ```yaml
  kube-controller-manager-arg:
    - node-cidr-mask-size=22
  ```

- Note: Using a very small mask (e.g., `/16`) allocates an oversized block per node and hurts horizontal scaling by limiting the number of workers you can add.

## Add Container Image Registry

k3s can pull images from public registries out of the box. If you need to use a **private** container image registry, you can add it to k3s via the `registries.yaml` configuration file.

Run the following commands on the machine where the k3s control-panel is located:

- `sudo nano /etc/rancher/k3s/registries.yaml`

- Edit the `mirrors` setting below to specify the address of the image registry you need

  ```yaml
  mirrors:
    "container.ctf.example.com": # change this to your registry's domain
      endpoint:
        - "https://container.ctf.example.com" # change this to your registry's domain
  ```

- `sudo systemctl restart k3s`
