Lightweight Docker image for running vsftpd on Alpine Linux.
License: MIT
- Small Alpine-based image
- Simple user provisioning via a flat file
- Automatic FTP user creation on container startup
- Persistent FTP storage using Docker volumes
- Passive mode support
- Configurable via mounted config/users files
- Healthcheck included
- Uses
tinias PID 1
docker run -d \
--name vsftpd \
-p 21:21 \
-p 30000-30010:30000-30010 \
-v vsftpd-data:/var/ftp \
kamaranl/vsftpddocker build -t docker-vsftpd .docker run -d \
--name vsftpd \
-p 21:21 \
-p 30000-30010:30000-30010 \
-v vsftpd-data:/var/ftp \
docker-vsftpdservices:
vsftpd:
image: docker-vsftpd
container_name: vsftpd
restart: unless-stopped
ports:
- "21:21"
- "30000-30010:30000-30010"
environment:
TZ: America/New_York
volumes:
- ./users.list:/etc/vsftpd/users.list:ro
- vsftpd-data:/var/ftp
configs:
- source: users_list
target: /etc/vsftpd/users.list
volumes:
vsftpd-data:
configs:
users_list:
file: ./users.listUsers are managed through a flat file.
Default location inside the container:
/etc/vsftpd/users.list
Format:
username:password
Example:
alice:supersecret
bob:hunter2
The container will automatically create a default user if no users are defined:
ftpadmin:ftpadmin
If a username and password are found to be identical, the password will automatically be changed to:
changemenow
Example:
alice:alice
Becomes:
alice:changemenow
The ftpadmin user is excluded from this behavior.
Create a local file:
users.list
Contents:
alice:password123
bob:password456
Run the container:
docker run -d \
--name vsftpd \
-p 21:21 \
-p 30000-30010:30000-30010 \
-v $(pwd)/users.list:/etc/vsftpd/users.list:ro \
-v vsftpd-data:/var/ftp \
docker-vsftpdEach user receives their own home directory automatically:
/var/ftp/<username>
Example:
/var/ftp/alice
/var/ftp/bob
Permissions are automatically corrected during container startup.
The default configuration is copied to:
/etc/vsftpd/vsftpd.conf
You can mount your own configuration file:
docker run -d \
--name vsftpd \
-p 21:21 \
-p 30000-30010:30000-30010 \
-v $(pwd)/vsftpd.conf:/etc/vsftpd/vsftpd.conf:ro \
-v vsftpd-data:/var/ftp \
docker-vsftpdanonymous_enable=NO
local_enable=YES
write_enable=YES
chroot_local_user=YES
pasv_min_port=30000
pasv_max_port=30010
xferlog_enable=YES
log_ftp_protocol=NO
seccomp_sandbox=NO
local_root=/var/ftp/| Component | Version |
|---|---|
| Alpine Linux | 3.23 |
| vsftpd | 3.0.5-r3 |
| Variable | Default | Description |
|---|---|---|
TZ |
UTC |
Container timezone |
USERS_FILE |
/etc/vsftpd/users.list |
Path to users file |
| Port | Description |
|---|---|
21 |
FTP control connection |
30000-30010 |
Passive FTP ports |
| Path | Description |
|---|---|
/var/ftp |
FTP user home directories and storage |
The image includes a built-in Docker healthcheck that validates the FTP service is responding on port 21.
- Anonymous FTP access is disabled by default
- Users are chrooted into their home directories
- Consider using strong passwords
- FTP is not encrypted by default; consider enabling TLS if exposing publicly
MIT © 2026 Kamaran Layne