Skip to content

feat:Add Docker Engine Support#66

Open
hikalif wants to merge 1 commit intoinclusionAI:mainfrom
hikalif:feature/docker-engine-support
Open

feat:Add Docker Engine Support#66
hikalif wants to merge 1 commit intoinclusionAI:mainfrom
hikalif:feature/docker-engine-support

Conversation

@hikalif
Copy link

@hikalif hikalif commented Feb 9, 2026

Docker Engine Support for AEnvironment

linked Issue: #14

Overview

AEnvironment now supports Docker Engine as a lightweight sandbox alternative to Kubernetes, enabling local development, CI/CD integration, and small-scale deployments without the complexity of a full Kubernetes cluster.

Key Features

1. Single Container Deployment

  • Create isolated Docker containers for environment instances
  • Resource limits (CPU, Memory) configuration
  • Custom network modes (bridge, host, custom)
  • Environment variable injection
  • Health checks on port 8081
  • Automatic TTL-based cleanup

2. Docker Compose Support

  • Multi-container environment deployments
  • Full Compose YAML specification support
  • Automatic service discovery
  • Main service selection for IP assignment
  • Stack lifecycle management (create, query, delete)

3. Multiple Connection Modes

  • Local Docker: Unix socket (unix:///var/run/docker.sock)
  • Remote Docker: TCP with TLS (tcp://host:2376)
  • Docker Desktop: Automatic detection on macOS/Windows
  • Docker Swarm: Service-based deployment (future)
  • Docker-in-Docker: CI/CD integration support

4. Production-Ready Features

  • Container state caching (30s sync interval)
  • Expired container cleanup based on TTL
  • Resource limit enforcement
  • Label-based filtering and management
  • API version negotiation
  • Health monitoring and restart policies

Detailed docs

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @hikalif, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces Docker Engine support to AEnvironment, providing a lightweight and flexible alternative to Kubernetes for managing environment instances. This enhancement is designed to streamline local development, simplify CI/CD pipelines, and enable deployments on resource-constrained edge devices by leveraging Docker's native capabilities for single containers and multi-container Compose stacks.

Highlights

  • Docker Engine Support: AEnvironment now supports Docker Engine as a lightweight sandbox alternative to Kubernetes, enabling local development, CI/CD integration, and small-scale deployments without the complexity of a full Kubernetes cluster.
  • Single Container Deployment: Introduced the ability to create isolated Docker containers with configurable resource limits (CPU, Memory), custom network modes, environment variable injection, health checks on port 8081, and automatic TTL-based cleanup.
  • Docker Compose Support: Added comprehensive support for multi-container environment deployments using Docker Compose, including full Compose YAML specification, automatic service discovery, main service selection for IP assignment, and stack lifecycle management.
  • Multiple Connection Modes: The system now supports various Docker connection modes: local Docker (Unix socket), remote Docker (TCP with TLS), automatic Docker Desktop detection, and Docker-in-Docker for CI/CD integration.
  • Production-Ready Features: Implemented container state caching with a 30-second sync interval, expired container cleanup based on TTL, robust resource limit enforcement, label-based filtering and management, and Docker API version negotiation for broader compatibility.
  • Go Version Rollback: The project's Go version was rolled back to 1.21 to ensure broader compatibility with various environments and CI/CD systems, with dependencies downgraded to compatible versions.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • .pre-commit-config.yaml
    • Updated versions for various pre-commit hooks including general hooks, Black formatter, isort import sorter, Ruff linter, golangci-lint, markdownlint, yamllint, and hadolint.
  • aenv/builtin-envs/terminalbench/src/client.py
    • Added a blank line for formatting consistency.
  • aenv/builtin-envs/terminalbench/src/tmuxsession.py
    • Added a blank line for formatting consistency.
  • aenv/src/aenv/core/environment.py
    • Modified environment URL construction logic to prioritize data_url (for Docker mode) over ip (for Kubernetes mode) when available.
  • aenv/src/aenv/core/models.py
    • Added an optional data_url field to the EnvInstance model to store the MCP data endpoint URL, primarily for Docker mode.
  • aenv/src/cli/cmds/init.py
    • Added a blank line for formatting consistency.
  • aenv/src/cli/cmds/instance.py
    • Added a blank line for formatting consistency.
  • aenv/src/cli/cmds/list.py
    • Added a blank line for formatting consistency.
  • aenv/src/cli/cmds/pull.py
    • Added a blank line for formatting consistency.
  • aenv/src/cli/cmds/push.py
    • Added a blank line for formatting consistency.
  • aenv/src/cli/cmds/service.py
    • Added a blank line for formatting consistency.
    • Adjusted a console print statement for better formatting.
  • aenv/src/cli/cmds/version.py
    • Added a blank line for formatting consistency.
  • aenv/src/cli/data/version_info.json
    • Added a new file containing version information for the AEnvironment CLI.
  • aenv/src/cli/tests/test_build_cmd.py
    • Added a blank line for formatting consistency.
  • aenv/src/cli/tests/test_instances.py
    • Added a blank line for formatting consistency.
  • aenv/src/cli/tests/test_singleton.py
    • Added a blank line for formatting consistency.
  • aenv/src/cli/utils/init.py
    • Added a blank line for formatting consistency.
  • aenv/src/cli/utils/config.py
    • Added a blank line for formatting consistency.
  • aenv/src/cli/utils/scaffold.py
    • Added a blank line for formatting consistency.
  • aenv/src/cli/utils/table_formatter.py
    • Added a blank line for formatting consistency.
  • api-service/Dockerfile
    • Added ca-certificates to the builder stage for improved security and connectivity.
    • Updated dependency download logic to support Go workspace mode, ensuring modules are present at the workspace root.
  • api-service/controller/env_instance.go
    • Modified CreateEnvInstance to gracefully handle cases where the backend is unavailable or the environment is not found, creating a default environment configuration suitable for Docker mode.
  • api-service/go.mod
    • Updated Go module dependencies, including github.com/prometheus/client_golang to v1.16.0 and github.com/spf13/pflag to v1.0.9.
    • Added k8s.io/apimachinery v0.30.0-alpha.2 as a new dependency.
    • Simplified the replace directive for envhub.
  • api-service/go.sum
    • Updated checksums to reflect changes in api-service/go.mod.
  • api-service/main.go
    • Updated the description for the schedule-type pflag to include 'docker' as a supported sandbox service schedule type.
    • Added a new case for 'docker' in the main function's schedule type switch, initializing service.NewDockerClient for Docker Engine integration.
  • api-service/models/env_instance.go
    • Added a DataURL field to the EnvInstance struct to store the MCP data endpoint URL.
    • Updated NewEnvInstance, NewEnvInstanceWithOwner, NewEnvInstanceWithStatus, NewEnvInstanceFull, and UpdateIP methods to correctly set and update the DataURL based on the instance's IP.
  • api-service/service/docker_client.go
    • Added a new file implementing DockerClient which provides an interface for interacting with the Docker Engine API, including methods for creating, getting, deleting, and listing containers, and implementing the EnvInstanceService interface for Docker-specific operations like cleanup.
  • controller/Dockerfile
    • Added ca-certificates and wget to the runtime stage for necessary utilities.
    • Set DOCKER_API_VERSION=1.44 environment variable to ensure compatibility with newer Docker daemon versions.
    • Updated dependency download logic to support Go workspace mode, ensuring modules are present at the workspace root.
  • controller/cmd/main.go
    • Modified the main function to conditionally initialize the Kubernetes controller manager or directly start the HTTP server based on the ENGINE_TYPE environment variable.
    • Introduced a readiness server on port 8081.
    • Updated the MapperProvider to use an httpClient for creating the lazy REST mapper, aligning with updated controller-runtime practices.
  • controller/go.mod
    • Added github.com/docker/docker v24.0.7+incompatible as a new dependency.
    • Updated Kubernetes API dependencies (k8s.io/api, k8s.io/apimachinery, k8s.io/client-go) to v0.28.4.
    • Updated sigs.k8s.io/controller-runtime to v0.16.3.
    • Added a replace directive for google.golang.org/genproto to resolve version conflicts and ensure Go 1.21 compatibility.
  • controller/go.sum
    • Updated checksums to reflect changes in controller/go.mod.
  • controller/pkg/aenvhub_http_server/aenv_docker_cache.go
    • Added a new file implementing AEnvDockerCache for caching Docker container states, including background synchronization with the Docker daemon and logic for detecting expired containers.
  • controller/pkg/aenvhub_http_server/aenv_docker_compose.go
    • Added a new file implementing ComposeProject and functions for managing Docker Compose stacks, including creating, deleting, detecting compose commands, and injecting AEnv metadata labels into compose files.
  • controller/pkg/aenvhub_http_server/aenv_docker_handler.go
    • Added a new file implementing AEnvDockerHandler to manage Docker container CRUD operations via HTTP, supporting both single container deployments and Docker Compose stacks, with TLS and network configuration.
  • controller/pkg/aenvhub_http_server/aenv_http_types.go
    • Added a new file defining common HTTP response structures (HttpResponseData, HttpResponse, HttpDeleteResponse, HttpListResponseData, HttpListResponse) for consistency across Docker handlers.
  • controller/pkg/aenvhub_http_server/aenv_pod_handler.go
    • Removed HTTP response type definitions, which were refactored into aenv_http_types.go for shared use.
  • controller/pkg/model/docker_config.go
    • Added a new file defining the DockerConfig struct and DefaultDockerConfig function for managing Docker engine specific configurations.
  • deploy/api-service/templates/_helpers.tpl
    • Removed trailing blank lines for formatting consistency.
  • deploy/api-service/values.yaml
    • Added scheduleType and scheduleAddr configuration parameters to allow specifying the sandbox engine and controller service address.
  • deploy/controller/templates/deployment.yaml
    • Added environment variables for Docker configuration (ENGINE_TYPE, DOCKER_HOST, DOCKER_TLS_VERIFY, DOCKER_CERT_PATH, DOCKER_NETWORK, COMPOSE_ENABLED) to the controller deployment.
    • Added volume mounts for the Docker socket (/var/run/docker.sock) and Docker TLS certificates, conditionally based on Docker configuration.
  • deploy/controller/values.yaml
    • Added a new docker section to the Helm chart values for configuring Docker Engine support, including enabled, host, tls, network, compose, and resources settings.
  • docs/DOCKER_ENGINE_IMPLEMENTATION_REVIEW.md
    • Added a new file providing a detailed implementation review of the Docker Engine support, covering functional completeness, backward compatibility, code quality, and known limitations.
  • docs/DOCKER_ENGINE_SUPPORT.md
    • Added a new file documenting the Docker Engine support feature, including its overview, key features, architecture, configuration, API compatibility, and deployment scenarios.
  • docs/DOCKER_ENGINE_TESTING.md
    • Added a new file providing a comprehensive setup and testing guide for the Docker Engine support, including prerequisites, build steps, test scenarios, and troubleshooting.
  • docs/ROLLBACK_TO_GO_1_21.md
    • Added a new file documenting the decision and process of rolling back the Go version to 1.21, detailing dependency downgrades and verification steps for broader compatibility.
  • docs/guide/environments.md
    • Minor formatting change in a table header.
  • docs/guide/sdk.md
    • Minor formatting change in a table header.
  • examples/docker_all_in_one/.gitignore
    • Added a new .gitignore file for the Docker example directory.
  • examples/docker_all_in_one/QUICK_START.md
    • Added a new quick start guide for the Docker Engine demo.
  • examples/docker_all_in_one/README.md
    • Added a new comprehensive README for the AEnvironment Docker Engine Mode example, covering overview, quick start, architecture, prerequisites, detailed usage, API examples, and troubleshooting.
  • examples/docker_all_in_one/README_COMPLETE_GUIDE.md
    • Added a new complete running guide for the AEnvironment Docker All-in-One Demo, including setup, verification, troubleshooting, and key configurations.
  • examples/docker_all_in_one/aenv-config.yaml
    • Added a new aenv CLI configuration file optimized for local Docker Engine development.
  • examples/docker_all_in_one/docker-compose.yml
    • Added a new Docker Compose file defining services for the controller and API service, configured for Docker Engine mode with health checks and network setup.
  • examples/docker_all_in_one/env.example
    • Added a new example environment variable file for Docker Compose configuration.
  • examples/docker_all_in_one/scripts/build_with_cli.sh
    • Added a new script to build the weather-demo image using the aenv CLI.
  • examples/docker_all_in_one/scripts/demo.sh
    • Added a new script for a full automated demo of AEnvironment in Docker mode, including service startup, image building, client execution, and cleanup options.
  • examples/docker_all_in_one/scripts/start.sh
    • Added a new script to start AEnvironment services in Docker mode, including Docker daemon checks, image building, and health verification.
  • examples/docker_all_in_one/scripts/stop.sh
    • Added a new script to stop AEnvironment services in Docker mode, with an option for cleanup of all AEnv-related containers and networks.
  • examples/docker_all_in_one/scripts/validate.sh
    • Added a new script to validate the structure and syntax of the Docker example files.
  • examples/docker_all_in_one/weather-demo/Dockerfile
    • Added a new Dockerfile for the weather-demo environment, setting up Python dependencies and the AEnvironment server command.
  • examples/docker_all_in_one/weather-demo/config.json
    • Added a new configuration file for the weather-demo environment, specifying metadata, image artifacts, and deploy configurations for Docker Engine mode.
  • examples/docker_all_in_one/weather-demo/requirements.txt
    • Added a new requirements.txt file listing Python dependencies for the weather-demo environment.
  • examples/docker_all_in_one/weather-demo/run_demo.py
    • Added a new Python script to demonstrate the usage of the weather-demo environment with Docker Engine mode, including creating, listing, calling tools/functions, and cleaning up environments.
  • examples/docker_all_in_one/weather-demo/src/custom_env.py
    • Added a new Python file containing custom environment logic for the weather-demo, including get_weather tool, get_weather_func function, and is_good_weather reward function.
  • scripts/verify_build.sh
    • Added a new script to verify the build process for Docker Engine support, checking Go installation, binary compilation, Docker availability, and the presence of new implementation files.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces significant new functionality by adding Docker Engine support as an alternative to Kubernetes. However, it contains critical security vulnerabilities related to insecure handling of user-controlled input when constructing and executing Docker Compose stacks. Specifically, path traversal vulnerabilities allow for arbitrary file write and deletion, and a YAML injection vulnerability enables attackers to inject malicious configurations, potentially leading to full host compromise. Beyond these critical security issues, there are also areas with code duplication and a potentially fragile implementation detail that could be improved for better long-term maintainability. These security issues must be addressed before merging.

Comment on lines +226 to +231
labels := fmt.Sprintf(`
labels:
- "aenv.env_name=%s"
- "aenv.version=%s"
- "aenv.owner="
- "aenv.project_id=%s"`, aenvHubEnv.Name, aenvHubEnv.Version, projectID)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-critical critical

The injectComposeLabels function is vulnerable to YAML injection because it constructs a YAML snippet by directly embedding user-controlled environment name and version using fmt.Sprintf without proper sanitization. An attacker can inject arbitrary YAML syntax, including host volume mounts, to compromise the host system. This string manipulation approach is fragile and can lead to incorrect YAML formatting even without malicious intent. It is critical to use a proper YAML parsing library (e.g., gopkg.in/yaml.v3) to safely parse, modify, and serialize the docker-compose.yml file. If string manipulation is unavoidable, all user-controlled inputs must be strictly validated and sanitized to prevent injection.

Comment on lines +71 to +73
composeFilePath := filepath.Join(tmpDir, fmt.Sprintf("aenv-compose-%s.yaml", projectID))

if err := os.WriteFile(composeFilePath, []byte(composeFileContent), 0644); err != nil {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-critical critical

The projectID is constructed using the environment name (aenvHubEnv.Name), which is user-controlled input from the api-service. This projectID is then used to construct a file path in /tmp without any sanitization or validation. An attacker can provide an environment name containing path traversal sequences (e.g., ../../) to cause the application to write the Docker Compose file to an arbitrary location on the host system. For example, an environment name like ../../etc/cron.d/evil could result in a file being written to /etc/cron.d/, potentially leading to remote code execution on the host.

Remediation: Sanitize the environment name to ensure it only contains alphanumeric characters and hyphens, and validate that it does not contain path traversal sequences before using it to construct file paths.

Comment on lines +281 to +312
composeFilePath := filepath.Join("/tmp", fmt.Sprintf("aenv-compose-%s.yaml", projectID))

klog.Infof("Deleting compose stack %s", projectName)

// Check if compose file exists
if _, err := os.Stat(composeFilePath); os.IsNotExist(err) {
klog.Warningf("Compose file not found: %s, will try to stop containers by label", composeFilePath)
return h.stopContainersByLabel(projectName)
}

// Detect compose command
composeCmd := h.detectComposeCommand()

// Execute docker-compose down
var cmd *exec.Cmd
if composeCmd == "docker compose" {
cmd = exec.Command("docker", "compose", "-f", composeFilePath, "-p", projectName, "down")
} else {
cmd = exec.Command("docker-compose", "-f", composeFilePath, "-p", projectName, "down")
}

output, err := cmd.CombinedOutput()
if err != nil {
klog.Errorf("Failed to stop compose stack: %v, output: %s", err, string(output))
// Try to stop containers manually
return h.stopContainersByLabel(projectName)
}

klog.Infof("Compose stack stopped: %s", string(output))

// Remove compose file
if err := os.Remove(composeFilePath); err != nil {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-high high

Similar to the creation flow, the deleteComposeStack function uses the user-supplied projectID to construct a file path for deletion. A path traversal vulnerability here allows an attacker to delete arbitrary files on the host system by providing a malicious projectID containing ../ sequences.

Remediation: Validate and sanitize the projectID to ensure it does not contain path traversal sequences before using it in file system operations.

Comment on lines +80 to 102
if ctrl.backendClient != nil {
backendEnv, err = ctrl.backendClient.GetEnvByVersion(name, version)
if err != nil {
// If backend is not available or env not found, create a default env for Docker mode
log.Infof("Backend not available or env not found, using default config for: %s@%s", name, version)
backendEnv = &backendmodels.Env{
Name: name,
Version: version,
DeployConfig: map[string]interface{}{
"imageName": fmt.Sprintf("aenv/%s:%s", name, version),
},
}
}
} else {
// No backend client, create default env
backendEnv = &backendmodels.Env{
Name: name,
Version: version,
DeployConfig: map[string]interface{}{
"imageName": fmt.Sprintf("aenv/%s:%s", name, version),
},
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The logic for creating a default backendEnv is duplicated in the if err != nil block and the else block. This can be refactored to reduce redundancy and improve maintainability. Consider a single point of creation for the default environment if backendEnv is nil after the initial attempt to fetch it from the backend.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant