mirror of
https://github.com/acedanger/docker.git
synced 2025-12-06 08:50:11 -08:00
284 lines
13 KiB
Markdown
284 lines
13 KiB
Markdown
Okay, let's switch gears to run Gitea using Docker and Docker Compose. This is generally the recommended approach as it isolates Gitea and its dependencies.
|
|
|
|
We'll still create a user on the *host* system to own the data volumes, ensuring correct permissions *outside* the container. The Gitea container itself runs internally as a user (usually `git`, UID/GID 1000 by default in the official image), and Docker maps the volume permissions.
|
|
|
|
**Key Components:**
|
|
|
|
1. **`docker-compose.yml`:** Defines the Gitea service and potentially a database service (e.g., PostgreSQL).
|
|
2. **Host Directory Structure:** Directories on the host machine to store persistent Gitea data (repos, config, database files, logs).
|
|
3. **Host User (`git`):** A user on the host system to own these directories, matching the UID/GID used inside the container.
|
|
4. **`app.ini`:** The Gitea configuration file, placed in the host directory structure to be mounted into the container.
|
|
|
|
**Steps:**
|
|
|
|
**1. Create Host User and Group (if they don't exist)**
|
|
|
|
We need a user and group on the host machine. We'll use the standard non-privileged UID/GID `1000`, which the official Gitea Docker image typically uses internally for its `git` user.
|
|
|
|
```bash
|
|
# Run these commands with sudo
|
|
sudo groupadd --gid 1000 git || echo "Group git (GID 1000) likely already exists."
|
|
sudo useradd --system --uid 1010 --gid 1010 --comment "Gitea Docker User" --shell /usr/sbin/nologin --home /opt/gitea git || echo "User git (UID 1010) likely already exists."
|
|
# Verify (optional)
|
|
id git
|
|
```
|
|
|
|
* If UID/GID 1000 is already taken on your system, choose another (e.g., 1001) and make sure to specify it in the `docker-compose.yml` using `user: UID:GID`. However, sticking to 1000 is often simplest if possible.
|
|
* `--shell /usr/sbin/nologin` prevents this user from being used for interactive logins.
|
|
* `--home /opt/gitea` sets a nominal home directory, though we won't rely on it directly.
|
|
|
|
**2. Create Host Directory Structure and Initial `app.ini`**
|
|
|
|
We'll create a directory (e.g., `/opt/gitea`) on the host to hold all persistent data and configuration.
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
|
|
# Exit immediately if a command exits with a non-zero status.
|
|
set -e
|
|
|
|
# --- Configuration ---
|
|
HOST_GITEA_ROOT="/opt/gitea" # Or choose another location like /srv/gitea
|
|
HOST_GITEA_DATA_DIR="${HOST_GITEA_ROOT}/data"
|
|
HOST_GITEA_CONFIG_DIR="${HOST_GITEA_ROOT}/config" # Gitea image expects config in /data/gitea/conf
|
|
HOST_GITEA_LOG_DIR="${HOST_GITEA_ROOT}/log" # We'll mount this separately for clarity
|
|
HOST_USER_UID=1010 # Must match the UID used inside the container (or specified in docker-compose)
|
|
HOST_USER_GID=1010 # Must match the GID used inside the container (or specified in docker-compose)
|
|
|
|
# --- Pre-checks ---
|
|
if [[ $EUID -ne 0 ]]; then
|
|
echo "This script must be run as root (or using sudo)"
|
|
exit 1
|
|
fi
|
|
if ! getent passwd "${HOST_USER_UID}" > /dev/null 2>&1; then
|
|
echo "ERROR: User with UID ${HOST_USER_UID} does not exist. Please create it first."
|
|
exit 1
|
|
fi
|
|
if ! getent group "${HOST_USER_GID}" > /dev/null 2>&1; then
|
|
echo "ERROR: Group with GID ${HOST_USER_GID} does not exist. Please create it first."
|
|
exit 1
|
|
fi
|
|
|
|
|
|
echo "--- Gitea Docker Host Setup ---"
|
|
|
|
# --- Create Directories ---
|
|
echo "[1/3] Creating host directories in ${HOST_GITEA_ROOT}..."
|
|
mkdir -pv "${HOST_GITEA_DATA_DIR}"
|
|
mkdir -pv "${HOST_GITEA_CONFIG_DIR}"
|
|
mkdir -pv "${HOST_GITEA_LOG_DIR}"
|
|
echo "Host directories created."
|
|
|
|
# --- Create Minimal app.ini ---
|
|
# Note: Gitea container expects app.ini at /data/gitea/conf/app.ini
|
|
# We will mount HOST_GITEA_CONFIG_DIR to /etc/gitea for easier access,
|
|
# but Gitea might ignore it if /data/gitea/conf/app.ini exists from the volume mount.
|
|
# A safer approach is often to let Gitea create the first config inside the /data mount
|
|
# and then modify it, or mount the specific file. Let's mount the dir /etc/gitea for now.
|
|
|
|
GITEA_CONF_FILE="${HOST_GITEA_CONFIG_DIR}/app.ini"
|
|
echo "[2/3] Creating minimal configuration file: ${GITEA_CONF_FILE}..."
|
|
|
|
cat << EOF > "${GITEA_CONF_FILE}"
|
|
; Example Gitea Configuration File for Docker
|
|
; Paths here usually refer to locations INSIDE the container.
|
|
; For details, see: https://docs.gitea.com/administration/config-cheat-sheet
|
|
|
|
APP_NAME = Gitea Docker
|
|
RUN_USER = git ; User inside the container
|
|
RUN_MODE = prod
|
|
|
|
[server]
|
|
DOMAIN = git.ptrwd.com ; CHANGE THIS to your actual domain/IP
|
|
HTTP_PORT = 3000 ; Port inside the container
|
|
ROOT_URL = http://git.ptrwd.com:3000/ ; CHANGE THIS along with DOMAIN
|
|
DISABLE_SSH = false
|
|
SSH_DOMAIN = %(DOMAIN)s ; Use value from DOMAIN
|
|
SSH_PORT = 22 ; Port inside the container (we map 2222 to this externally)
|
|
SSH_LISTEN_PORT = 22 ; Make built-in SSH listen on port 22 inside the container
|
|
START_SSH_SERVER = true ; Use the built-in SSH server
|
|
LFS_START_SERVER = true
|
|
LFS_CONTENT_PATH = /data/gitea/lfs ; Path inside the container
|
|
|
|
[repository]
|
|
ROOT = /data/git/gitea-repositories ; Path inside the container
|
|
|
|
[log]
|
|
ROOT_PATH = /data/log ; Path inside container (maps to HOST_GITEA_LOG_DIR)
|
|
MODE = console,file ; Log to console (for docker logs) and file
|
|
LEVEL = Info
|
|
|
|
[database]
|
|
; === IMPORTANT: Configure your database ===
|
|
; Option 1: SQLite3 (Simplest, place DB inside the data volume)
|
|
DB_TYPE = sqlite3
|
|
PATH = /data/gitea/gitea.db ; Path inside the container
|
|
;
|
|
; Option 2: PostgreSQL (Recommended for production, use docker-compose service name as host)
|
|
; DB_TYPE = postgres
|
|
; HOST = db:5432 ; 'db' is the service name in docker-compose.yml
|
|
; NAME = gitea
|
|
; USER = gitea
|
|
; PASSWD = 'YOUR_POSTGRES_PASSWORD' ; Use secrets or env vars in real setup
|
|
; SSL_MODE = disable
|
|
;
|
|
; Option 3: MySQL
|
|
; DB_TYPE = mysql
|
|
; HOST = db:3306 ; 'db' is the service name in docker-compose.yml
|
|
; NAME = gitea
|
|
; USER = gitea
|
|
; PASSWD = 'YOUR_MYSQL_PASSWORD' ; Use secrets or env vars in real setup
|
|
; CHARSET = utf8mb4
|
|
|
|
[service]
|
|
REGISTER_EMAIL_CONFIRM = false
|
|
ENABLE_NOTIFY_MAIL = false
|
|
DISABLE_REGISTRATION = false
|
|
ENABLE_CAPTCHA = false
|
|
REQUIRE_SIGNIN_VIEW = false
|
|
|
|
[security]
|
|
INSTALL_LOCK = true ; Set to true AFTER first install via web UI
|
|
SECRET_KEY = PLEASE_CHANGE_ME_SECRET_KEY_! ; CHANGE THIS! Generate with 'docker exec <container_name> gitea generate secret SECRET_KEY'
|
|
INTERNAL_TOKEN = PLEASE_CHANGE_ME_INTERNAL_TOKEN_! ; CHANGE THIS! Generate with 'docker exec <container_name> gitea generate secret INTERNAL_TOKEN'
|
|
PASSWORD_HASH_ALGO = pbkdf2 ; Default and recommended
|
|
|
|
[session]
|
|
PROVIDER = file
|
|
PROVIDER_CONFIG = /data/sessions ; Path inside the container
|
|
|
|
[picture]
|
|
AVATAR_UPLOAD_PATH = /data/gitea/avatars ; Path inside the container
|
|
REPOSITORY_AVATAR_UPLOAD_PATH = /data/gitea/repo-avatars ; Path inside the container
|
|
|
|
[attachment]
|
|
PATH = /data/gitea/attachments ; Path inside the container
|
|
|
|
EOF
|
|
echo "Minimal ${GITEA_CONF_FILE} created."
|
|
echo " >> IMPORTANT: Review and edit ${GITEA_CONF_FILE} with your specific settings (DOMAIN, ROOT_URL, Database, Secret Keys)!"
|
|
|
|
# --- Set Ownership ---
|
|
echo "[3/3] Setting ownership for ${HOST_GITEA_ROOT} to ${HOST_USER_UID}:${HOST_USER_GID}..."
|
|
chown -R "${HOST_USER_UID}":"${HOST_USER_GID}" "${HOST_GITEA_ROOT}"
|
|
# Set permissions (optional, ownership is key for docker volumes)
|
|
# chmod -R u+rwX,go= "${HOST_GITEA_ROOT}" # Give owner full control, deny group/others
|
|
chmod 750 "${HOST_GITEA_ROOT}" # Owner rwx, group rx, others ---
|
|
find "${HOST_GITEA_ROOT}" -type d -exec chmod 750 {} \; # Dirs: owner rwx, group rx
|
|
find "${HOST_GITEA_ROOT}" -type f -exec chmod 640 {} \; # Files: owner rw, group r
|
|
echo "Ownership and basic permissions set."
|
|
|
|
echo "--- Host Setup Complete ---"
|
|
echo "Next steps:"
|
|
echo "1. **CRITICAL:** Edit ${GITEA_CONF_FILE} for your specific needs (Domain, Database, Secrets!)."
|
|
echo "2. Create the docker-compose.yml file."
|
|
echo "3. Run 'docker compose up -d' in the directory containing docker-compose.yml."
|
|
```
|
|
|
|
**How to use the script:**
|
|
|
|
1. Save the script (e.g., `setup_docker_gitea_host.sh`).
|
|
2. Make it executable: `chmod +x setup_docker_gitea_host.sh`.
|
|
3. Run with sudo: `sudo ./setup_docker_gitea_host.sh`.
|
|
4. **Crucially, edit the generated `/opt/gitea/config/app.ini` file** with your actual domain, database choice, and generate/set real secret keys *before* starting the container.
|
|
|
|
**3. Create `docker-compose.yml`**
|
|
|
|
Create this file in a convenient location (e.g., in `/opt/gitea` or a dedicated project directory). This example uses PostgreSQL, which is recommended for production.
|
|
|
|
```yaml
|
|
# /opt/gitea/docker-compose.yml
|
|
# or ~/gitea-docker/docker-compose.yml
|
|
|
|
networks:
|
|
gitea-net:
|
|
external: false
|
|
|
|
services:
|
|
gitea:
|
|
image: gitea/gitea:latest # Use a specific version tag in production, e.g., :1.21.5
|
|
container_name: gitea
|
|
restart: always
|
|
environment:
|
|
# All config is primarily done via app.ini now, but you could pass some simpler ones here
|
|
- USER_UID=1010 # Matches the host user created
|
|
- USER_GID=1010 # Matches the host group created
|
|
- GITEA__database__DB_TYPE=postgres # Example: Overriding app.ini via env var if needed
|
|
- GITEA__database__HOST=db:5432 # Using double underscore convention
|
|
- GITEA__database__NAME=gitea
|
|
- GITEA__database__USER=gitea
|
|
- GITEA__database__PASSWD=gitea_password # CHANGE THIS! Use docker secrets ideally
|
|
networks:
|
|
- gitea-net
|
|
volumes:
|
|
# Mount the main data directory from the host
|
|
- ./data:/data # Maps host's ./data (relative to compose file) to container's /data
|
|
# Mount the config directory separately (optional, but explicit)
|
|
- ./config:/etc/gitea # Maps host's ./config to container's /etc/gitea
|
|
# Mount log directory
|
|
- ./log:/data/log # Maps host's ./log to container's /data/log (matches app.ini)
|
|
# Timezone consistency
|
|
- /etc/timezone:/etc/timezone:ro
|
|
- /etc/localtime:/etc/localtime:ro
|
|
ports:
|
|
- "3000:3000" # Map host port 3000 to container port 3000 (HTTP)
|
|
- "2222:22" # Map host port 2222 to container port 22 (SSH)
|
|
depends_on:
|
|
db:
|
|
condition: service_healthy # Wait for postgres to be healthy
|
|
|
|
db:
|
|
image: postgres:15 # Use a specific version
|
|
container_name: gitea-db
|
|
restart: always
|
|
environment:
|
|
- POSTGRES_USER=gitea # CHANGE THIS if needed
|
|
- POSTGRES_PASSWORD=gitea_password # CHANGE THIS! Must match GITEA__database__PASSWD
|
|
- POSTGRES_DB=gitea # CHANGE THIS if needed
|
|
networks:
|
|
- gitea-net
|
|
volumes:
|
|
# Persist postgres data on the host - create a 'postgres' dir next to 'data', 'config', 'log'
|
|
- ./postgres:/var/lib/postgresql/data
|
|
healthcheck:
|
|
# Basic check to see if postgres is ready to accept connections
|
|
test: ["CMD-SHELL", "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"]
|
|
interval: 10s
|
|
timeout: 5s
|
|
retries: 5
|
|
|
|
volumes:
|
|
gitea_data:
|
|
gitea_config:
|
|
postgres_data:
|
|
|
|
```
|
|
|
|
**Explanation:**
|
|
|
|
* **`user: "1000:1000"` (Optional but good practice):** You can explicitly add this under the `gitea:` service definition to force the container process to run as UID/GID 1000, ensuring it matches the host directory ownership. The official image usually handles this, but being explicit can prevent permission issues.
|
|
* **Volumes (`./data:/data`, etc.):** We use *bind mounts*. This maps the directories we created on the host (`/opt/gitea/data`, `/opt/gitea/config`, etc.) directly into the specified paths inside the container. Docker uses the ownership we set on the host directories (`chown 1000:1000`).
|
|
* **`app.ini` Location:** The Gitea image typically looks for `app.ini` within its data directory (`/data/gitea/conf/app.ini`). By mounting `./config:/etc/gitea` and `./data:/data`, the container *should* find the config. If you have issues, you might need to adjust the volume mount for config or ensure the `app.ini` is placed at `/opt/gitea/data/gitea/conf/app.ini` on the host *before* starting. Mounting `/etc/gitea` is often cleaner if the image respects `GITEA_CUSTOM`. For simplicity, the setup script places it in `./config`, matching the volume mount. Adjust if Gitea doesn't pick it up.
|
|
* **Database:** The `db` service uses the official Postgres image. Its data is persisted in `./postgres` on the host. The Gitea container connects to it using the service name `db` as the hostname. **Change the default passwords!**
|
|
* **Ports:** `3000:3000` maps the web UI port. `2222:22` maps host port 2222 to the container's SSH port 22 (make sure your host's firewall allows port 2222).
|
|
* **Networks:** A dedicated network `gitea-net` allows the containers to communicate easily using service names (`gitea`, `db`).
|
|
* **Healthcheck:** Ensures Gitea only starts *after* PostgreSQL is ready.
|
|
|
|
**4. Running Gitea**
|
|
|
|
1. Navigate to the directory where you saved `docker-compose.yml` (e.g., `/opt/gitea`).
|
|
2. Ensure you have edited `/opt/gitea/config/app.ini` appropriately (Domain, DB, **Secrets**). Generate secrets using `docker run --rm gitea/gitea:latest gitea generate secret SECRET_KEY` etc., if needed.
|
|
3. Start the services in detached mode:
|
|
```bash
|
|
cd /opt/gitea
|
|
docker compose up -d
|
|
```
|
|
4. Check the logs:
|
|
```bash
|
|
docker compose logs -f gitea
|
|
docker compose logs -f db
|
|
```
|
|
5. Access Gitea in your browser at `http://<your-host-ip-or-domain>:3000`.
|
|
6. Clone via SSH using `ssh://git@<your-host-ip-or-domain>:2222/user/repo.git`.
|
|
|
|
This Docker setup provides isolation, easier dependency management (database), and uses host volumes with correct permissions managed by the `git` (UID/GID 1000) user on the host. |