A production-ready OpenSSH server Docker image based on Debian, designed for secure remote access.
618
A production-ready OpenSSH server Docker image based on Debian Bookworm, designed for secure remote access, development environments, and CI/CD pipelines.
/app volume# Pull the image
docker pull optimode/openssh:latest
# Create config directory
mkdir -p ./config/.ssh
# Add your SSH public key
cat ~/.ssh/id_rsa.pub > ./config/.ssh/authorized_keys
# Run the container
docker run -d \
--name openssh \
-p 2222:2222 \
-v ./config:/app \
-e USER_NAME=devuser \
-e PUID=1000 \
-e PGID=1000 \
optimode/openssh:latest
# Connect
ssh -p 2222 devuser@localhost
Create a docker-compose.yml file:
services:
openssh:
image: optimode/openssh:latest
container_name: openssh
restart: unless-stopped
ports:
- "2222:2222"
volumes:
- ./config:/app
- ./workspace:/workspace
environment:
- TZ=Europe/Budapest
- PUID=1000
- PGID=1000
- USER_NAME=devuser
- SUDO_ACCESS=false
- PASSWORD_ACCESS=false
Then run:
# Add your SSH public key
mkdir -p ./config/.ssh
cat ~/.ssh/id_rsa.pub > ./config/.ssh/authorized_keys
# Start the container
docker-compose up -d
# Connect
ssh -p 2222 devuser@localhost
| Variable | Default | Description |
|---|---|---|
USER_NAME | app | Username for SSH access |
PUID | 911 | User ID (useful for matching host user permissions) |
PGID | 911 | Group ID (useful for matching host group permissions) |
USER_HOME | /app | User home directory |
USER_PASSWORD | <random> | User password (auto-generated if not set) |
USER_PASSWORD_FILE | - | Path to file containing password (Docker secrets) |
| Variable | Default | Description |
|---|---|---|
LISTEN_PORT | 2222 | SSH server listening port |
PASSWORD_ACCESS | false | Enable/disable password authentication |
PUBLIC_KEY | - | SSH public key (single key as string) |
PUBLIC_KEY_FILE | - | Path to file containing a public key |
PUBLIC_KEY_DIR | - | Path to directory containing multiple key files |
| Variable | Default | Description |
|---|---|---|
SUDO_ACCESS | false | Grant sudo privileges to the user |
UMASK | 022 | Default umask for file creation |
| Variable | Default | Description |
|---|---|---|
TZ | UTC | Timezone (e.g., Europe/Budapest, America/New_York) |
| Path | Purpose |
|---|---|
/app | Required - Persistent storage for SSH config, host keys, and user data |
/workspace | Optional - Additional workspace directory |
| Port | Protocol | Description |
|---|---|---|
2222 | TCP | SSH server port (configurable via LISTEN_PORT) |
There are multiple ways to provide SSH public keys for authentication:
mkdir -p ./config/.ssh
cat ~/.ssh/id_rsa.pub > ./config/.ssh/authorized_keys
chmod 600 ./config/.ssh/authorized_keys
environment:
- PUBLIC_KEY=ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAB...
environment:
- PUBLIC_KEY_FILE=/secrets/ssh-key.pub
volumes:
- ./my-key.pub:/secrets/ssh-key.pub:ro
environment:
- PUBLIC_KEY_DIR=/secrets/keys
volumes:
- ./keys:/secrets/keys:ro
Multiple methods can be used simultaneously - all keys will be added to authorized_keys.
services:
devssh:
image: optimode/openssh:latest
container_name: devssh
ports:
- "2222:2222"
volumes:
- ./config:/app
- ./projects:/workspace
- /var/run/docker.sock:/var/run/docker.sock # Docker-in-Docker
environment:
- USER_NAME=developer
- PUID=1000
- PGID=1000
- SUDO_ACCESS=true
- PASSWORD_ACCESS=false
- TZ=America/New_York
services:
openssh:
image: optimode/openssh:latest
container_name: openssh-pass
ports:
- "2222:2222"
volumes:
- ./config:/app
environment:
- USER_NAME=testuser
- USER_PASSWORD=SecurePassword123
- PASSWORD_ACCESS=true
- SUDO_ACCESS=false
services:
openssh:
image: optimode/openssh:latest
container_name: openssh-secure
ports:
- "2222:2222"
volumes:
- ./config:/app
secrets:
- ssh_password
environment:
- USER_NAME=admin
- USER_PASSWORD_FILE=/run/secrets/ssh_password
- PASSWORD_ACCESS=true
secrets:
ssh_password:
file: ./secrets/password.txt
services:
openssh:
image: optimode/openssh:latest
container_name: openssh-custom
ports:
- "2200:2200"
volumes:
- ./config:/app
environment:
- LISTEN_PORT=2200
- USER_NAME=sshuser
- TZ=Asia/Tokyo
- PUID=1001
- PGID=1001
# Clone the repository
git clone https://github.com/optimode/openssh.git
cd docker-openssh
# Build the image
./build
# Or use docker build directly
docker build -t optimode/openssh:latest .
/app/
├── .ssh/
│ └── authorized_keys # SSH public keys
├── sshd/
│ └── sshd_config # OpenSSH server configuration
├── ssh_host_keys/ # Persistent host keys
└── logs/
└── openssh/
└── sshd.log # SSH server logs with timestamps
Logs are stored in /app/logs/openssh/sshd.log with timestamps in format [YYYY-MM-DD HH:MM:SS TZ].
View logs:
# Real-time logs
docker logs -f openssh
# Persistent log file
docker exec openssh tail -f /app/logs/openssh/sshd.log
Problem: Cannot connect to SSH server
Solutions:
docker psdocker port opensshdocker exec openssh ps aux | grep sshdProblem: Authentication fails with public key
Solutions:
authorized_keys: docker exec openssh cat /app/.ssh/authorized_keysauthorized_keys, 700 for .sshssh -i ~/.ssh/id_rsa -p 2222 user@localhostdocker logs opensshProblem: Files in mounted volumes have wrong ownership
Solutions:
PUID and PGID to match your host user:
id -u # Get your UID
id -g # Get your GID
docker-compose down && docker-compose up -dProblem: User cannot write to /workspace directory
Solutions:
sudo chown -R 1000:1000 ./workspace # Use your PUID:PGID
chmod -R 755 ./workspace
Problem: Sudo commands fail despite SUDO_ACCESS=true
Solutions:
docker exec openssh env | grep SUDOdocker exec openssh cat /etc/sudoers | grep appUSER_PASSWORD is setSUDO_ACCESSssh-keygen -t ed25519 or ssh-keygen -t rsa -b 4096SUDO_ACCESS=true when necessary/app/logs/openssh/sshd.log for suspicious activityMIT License - See LICENSE file for details
Contributions are welcome! Please feel free to submit a Pull Request.
Optimode (Laszlo Malina)
Content type
Image
Digest
sha256:4666e36e2…
Size
154.4 MB
Last updated
11 months ago
docker pull optimode/openssh