simplifying docker workflow
This commit is contained in:
@@ -3,6 +3,9 @@ ADMIN_TOKEN=devadmintoken
|
|||||||
# Docker host binding (used by docker compose for port mapping)
|
# Docker host binding (used by docker compose for port mapping)
|
||||||
HOST=127.0.0.1
|
HOST=127.0.0.1
|
||||||
PORT=8080
|
PORT=8080
|
||||||
|
# User and group for file ownership (should match system user on host)
|
||||||
|
UID=1000
|
||||||
|
GID=1000
|
||||||
|
|
||||||
# Optional: Service configuration (defaults shown)
|
# Optional: Service configuration (defaults shown)
|
||||||
DEPLOY_ROOT=/var/www/docs
|
DEPLOY_ROOT=/var/www/docs
|
||||||
|
|||||||
@@ -1,11 +1,16 @@
|
|||||||
# Docker Compose Variables (used for port mapping)
|
# Docker Compose Variables (used for port mapping)
|
||||||
# Copy this file to .env for docker-compose to use
|
# Copy this file to .env for docker compose to use
|
||||||
|
|
||||||
# The Go service always binds to 0.0.0.0:8080 inside the container
|
# The Go service always binds to 0.0.0.0:8080 inside the container
|
||||||
HOST=0.0.0.0
|
HOST=0.0.0.0
|
||||||
PORT=8080
|
PORT=8080
|
||||||
|
# User and group for file ownership (MUST match system user on host)
|
||||||
|
UID=1000
|
||||||
|
GID=1000
|
||||||
|
|
||||||
# Required: Admin bearer token for API access
|
# Required: Admin bearer token for API access
|
||||||
ADMIN_TOKEN=your-secure-admin-token-here # TODO: generate a secure token
|
ADMIN_TOKEN=your-secure-admin-token-here
|
||||||
|
|
||||||
# Optional: Service configuration (defaults shown)
|
# Optional: Service configuration (defaults shown)
|
||||||
DEPLOY_ROOT=/var/www/tingz-docs
|
DEPLOY_ROOT=/var/www/tingz-docs
|
||||||
RELEASE_ROOT=/var/www/tingz-deploys
|
RELEASE_ROOT=/var/www/tingz-deploys
|
||||||
|
|||||||
10
Dockerfile
10
Dockerfile
@@ -17,12 +17,16 @@ RUN CGO_ENABLED=0 GOOS=linux GOARCH=${TARGETARCH} go build \
|
|||||||
|
|
||||||
FROM alpine:latest
|
FROM alpine:latest
|
||||||
|
|
||||||
RUN adduser -D -u 1000 deployer && \
|
ARG UID
|
||||||
chown -R deployer:deployer /tmp
|
ARG GID
|
||||||
|
|
||||||
|
RUN addgroup -g ${GID} -S tingz && \
|
||||||
|
adduser -u ${UID} -S -G tingz -s /sbin/nologin tingz && \
|
||||||
|
chown -R tingz:tingz /tmp
|
||||||
|
|
||||||
COPY --from=builder /bin/deployer /deployer
|
COPY --from=builder /bin/deployer /deployer
|
||||||
|
|
||||||
USER deployer
|
USER tingz
|
||||||
|
|
||||||
EXPOSE 8080
|
EXPOSE 8080
|
||||||
|
|
||||||
|
|||||||
@@ -1,14 +1,17 @@
|
|||||||
services:
|
services:
|
||||||
server:
|
server:
|
||||||
build: .
|
|
||||||
container_name: tingz-server
|
container_name: tingz-server
|
||||||
restart: unless-stopped
|
env_file: .env
|
||||||
env_file: .env.development
|
build:
|
||||||
|
context: .
|
||||||
|
args:
|
||||||
|
UID: ${UID}
|
||||||
|
GID: ${GID}
|
||||||
volumes:
|
volumes:
|
||||||
- ./data:/data
|
- ./data:/data
|
||||||
- ./docs:/var/www/docs
|
- ./docs:/var/www/docs
|
||||||
- ./deploys:/var/www/deploys
|
- ./deploys:/var/www/deploys
|
||||||
ports:
|
ports:
|
||||||
- "${HOST}:${PORT}:8080"
|
- "${HOST}:${PORT}:8080"
|
||||||
user: "1000:1000"
|
user: "${UID}:${GID}"
|
||||||
|
restart: unless-stopped
|
||||||
|
|||||||
@@ -68,6 +68,10 @@ func (m *Manager) Deploy(ctx context.Context, username, project string, r io.Rea
|
|||||||
return "", fmt.Errorf("failed to extract tarball: %w", err)
|
return "", fmt.Errorf("failed to extract tarball: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := m.lockdownPermissions(releasePath); err != nil {
|
||||||
|
return "", fmt.Errorf("failed to set read-only permissions: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
deployPath := filepath.Join(m.deployRoot, username, project)
|
deployPath := filepath.Join(m.deployRoot, username, project)
|
||||||
deployParentDir := filepath.Dir(deployPath)
|
deployParentDir := filepath.Dir(deployPath)
|
||||||
if err := os.MkdirAll(deployParentDir, 0755); err != nil {
|
if err := os.MkdirAll(deployParentDir, 0755); err != nil {
|
||||||
@@ -178,6 +182,26 @@ func validateTarPath(path string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *Manager) lockdownPermissions(root string) error {
|
||||||
|
return filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if info.IsDir() {
|
||||||
|
if err := os.Chmod(path, 0550); err != nil {
|
||||||
|
return fmt.Errorf("failed to chmod directory %s: %w", path, err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if err := os.Chmod(path, 0440); err != nil {
|
||||||
|
return fmt.Errorf("failed to chmod file %s: %w", path, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func (m *Manager) cleanupOldReleases(username, project string) error {
|
func (m *Manager) cleanupOldReleases(username, project string) error {
|
||||||
releasesDir := filepath.Join(m.releaseRoot, username, project)
|
releasesDir := filepath.Join(m.releaseRoot, username, project)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user