initial commit (second try)
This commit is contained in:
parent
a62cf65376
commit
ed3c0eae14
7 changed files with 656 additions and 0 deletions
208
docker.go
Normal file
208
docker.go
Normal file
|
@ -0,0 +1,208 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const hakoVersion = "1"
|
||||
|
||||
func getConfigDir() (string, error) {
|
||||
homeDir, err := os.UserHomeDir()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
configDir := filepath.Join(homeDir, ".config", "hako")
|
||||
return configDir, nil
|
||||
}
|
||||
|
||||
func ensureConfigDir() error {
|
||||
configDir, err := getConfigDir()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return os.MkdirAll(configDir, 0755)
|
||||
}
|
||||
|
||||
func getBaseDockerfile() string {
|
||||
return fmt.Sprintf(`# HAKO-VERSION=%s
|
||||
FROM debian:bookworm
|
||||
|
||||
RUN apt-get update && apt-get install -y \
|
||||
curl \
|
||||
git \
|
||||
build-essential \
|
||||
ca-certificates \
|
||||
fish \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Install Node.js LTS
|
||||
RUN curl -fsSL https://deb.nodesource.com/setup_lts.x | bash - \
|
||||
&& apt-get install -y nodejs
|
||||
|
||||
# Install Claude Code
|
||||
RUN npm install -g @anthropic-ai/claude-code
|
||||
|
||||
# configure some things
|
||||
RUN mkdir /workspace
|
||||
RUN git config --global --add safe.directory /workspace
|
||||
|
||||
WORKDIR /workspace
|
||||
CMD ["/usr/bin/fish"]`, hakoVersion)
|
||||
}
|
||||
|
||||
func getLanguageDockerfile(lang string) string {
|
||||
switch lang {
|
||||
case "go":
|
||||
return fmt.Sprintf(`# HAKO-VERSION=%s
|
||||
FROM hako-userland
|
||||
|
||||
RUN curl -fsSL https://go.dev/dl/go1.21.5.linux-amd64.tar.gz | tar -C /usr/local -xzf -
|
||||
ENV PATH="/usr/local/go/bin:${PATH}"
|
||||
|
||||
WORKDIR /workspace
|
||||
CMD ["/bin/bash"]`, hakoVersion)
|
||||
case "py", "python":
|
||||
return fmt.Sprintf(`# HAKO-VERSION=%s
|
||||
FROM hako-userland
|
||||
|
||||
RUN apt-get update && apt-get install -y \
|
||||
python3 \
|
||||
python3-pip \
|
||||
python3-venv \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
RUN ln -s /usr/bin/python3 /usr/bin/python
|
||||
|
||||
WORKDIR /workspace
|
||||
CMD ["/bin/bash"]`, hakoVersion)
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
func buildBaseImage() error {
|
||||
if err := ensureConfigDir(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
configDir, _ := getConfigDir()
|
||||
dockerfilePath := filepath.Join(configDir, "Dockerfile.base")
|
||||
|
||||
dockerfile := getBaseDockerfile()
|
||||
if err := os.WriteFile(dockerfilePath, []byte(dockerfile), 0644); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Printf("Building base image hako-userland...\n")
|
||||
return runCommand("docker", "build", "-f", dockerfilePath, "-t", "hako-userland", ".")
|
||||
}
|
||||
|
||||
func buildLanguageImage(lang string) error {
|
||||
dockerfile := getLanguageDockerfile(lang)
|
||||
if dockerfile == "" {
|
||||
return fmt.Errorf("unsupported language: %s", lang)
|
||||
}
|
||||
|
||||
configDir, err := getConfigDir()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dockerfilePath := filepath.Join(configDir, fmt.Sprintf("Dockerfile.%s", lang))
|
||||
if err := os.WriteFile(dockerfilePath, []byte(dockerfile), 0644); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
imageName := fmt.Sprintf("hako-userland-%s", lang)
|
||||
fmt.Printf("Building %s image %s...\n", lang, imageName)
|
||||
return runCommand("docker", "build", "-f", dockerfilePath, "-t", imageName, ".")
|
||||
}
|
||||
|
||||
func imageExists(imageName string) bool {
|
||||
err := runCommand("docker", "image", "inspect", imageName)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
func containerExists(containerName string) bool {
|
||||
err := runCommand("docker", "container", "inspect", containerName)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
func containerIsRunning(containerName string) bool {
|
||||
output, err := runCommandOutput("docker", "container", "inspect", "-f", "{{.State.Running}}", containerName)
|
||||
return err == nil && strings.TrimSpace(output) == "true"
|
||||
}
|
||||
|
||||
func createContainer(containerName, imageName, workspaceDir string) error {
|
||||
homeDir, err := os.UserHomeDir()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
args := []string{"create", "--name", containerName}
|
||||
|
||||
// Mount workspace
|
||||
args = append(args, "-v", workspaceDir+":/workspace")
|
||||
|
||||
|
||||
args = append(args, "-it", imageName)
|
||||
|
||||
if err := runCommand("docker", args...); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Copy Claude config directory if it exists
|
||||
claudeDir := filepath.Join(homeDir, ".claude")
|
||||
if _, err := os.Stat(claudeDir); err == nil {
|
||||
if err := copyToContainer(containerName, claudeDir, "/root/.claude"); err != nil {
|
||||
return fmt.Errorf("failed to copy Claude config directory: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Copy Claude config file if it exists
|
||||
claudeFile := filepath.Join(homeDir, ".claude.json")
|
||||
if _, err := os.Stat(claudeFile); err == nil {
|
||||
if err := copyToContainer(containerName, claudeFile, "/root/.claude.json"); err != nil {
|
||||
return fmt.Errorf("failed to copy Claude config file: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func startContainer(containerName string) error {
|
||||
return runCommand("docker", "start", containerName)
|
||||
}
|
||||
|
||||
func stopContainer(containerName string) error {
|
||||
return runCommand("docker", "stop", containerName)
|
||||
}
|
||||
|
||||
func removeContainer(containerName string) error {
|
||||
return runCommand("docker", "rm", containerName)
|
||||
}
|
||||
|
||||
func execContainer(containerName string) error {
|
||||
cmd := exec.Command("docker", "exec", "-it", containerName, "/usr/bin/fish")
|
||||
fmt.Fprintf(os.Stderr, "+ %s %s\n", "docker", strings.Join([]string{"exec", "-it", containerName, "/usr/bin/fish"}, " "))
|
||||
cmd.Stdin = os.Stdin
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
return cmd.Run()
|
||||
}
|
||||
|
||||
func copyToContainer(containerName, srcPath, destPath string) error {
|
||||
return runCommand("docker", "cp", srcPath, containerName+":"+destPath)
|
||||
}
|
||||
|
||||
func copyFromContainer(containerName, srcPath, destPath string) error {
|
||||
return runCommand("docker", "cp", containerName+":"+srcPath, destPath)
|
||||
}
|
||||
|
||||
func listHakoContainers() error {
|
||||
return runCommand("docker", "ps", "-a", "--filter", "name=hako-", "--format", "table {{.Names}}\\t{{.Status}}\\t{{.Image}}")
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue