Solving the MySQL Docker "Permission Denied" Error on Synology NAS: A Step-by-Step Guide
Content
## The Problem
Deploying MySQL using Docker on a Synology NAS is a common practice for setting up a reliable database service quickly. However, many users encounter a classic permission issue when mounting volumes, which causes the container to fail on startup. The logs typically show an error like `Could not open file '...' for error logging: Permission denied`. This article, based on a real-world case from `wiki.lib00.com`, will explain the cause of this problem and provide effective solutions.
---
## Reproducing the Failure
A developer, DP@lib00, attempted to deploy a `mysql:5.7.40` container, mapping volumes for configuration, logs, and data. Here are the two attempts and their outcomes.
### First Attempt: Failure
1. **Action**: The required folder structure, such as `/volume1/docker/mysql-5.7.40/logs` and `/volume1/docker/mysql-5.7.40/data`, was created using the Synology DSM File Station GUI.
2. **Docker Command**:
```bash
docker run -d --restart=always --name ee-mysql-5.7.40 -p 38756:3306 \
-v /volume1/docker/mysql-5.7.40/conf:/etc/mysql/conf.d \
-v /volume1/docker/mysql-5.7.40/logs:/logs \
-v /volume1/docker/mysql-5.7.40/data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=123456 \
mysql:5.7.40
```
3. **Error Log**: The container exited immediately after starting, with a clear permission error in the logs.
```log
2025-11-27T14:34:47.228587Z 0 [ERROR] Could not open file '/logs/error.log' for error logging: Permission denied
2025-11-27T14:34:47.228609Z 0 [ERROR] Aborting
```
### Second Attempt: Success
1. **Action**: The old directories were deleted. After logging into the Synology via SSH, the folders were recreated via the command line, and critically, the permissions for the `logs` and `data` directories were changed.
```bash
# 1. Create directories (steps omitted)
# 2. Change permissions
chmod 777 /volume1/docker/mysql-5.7.40/logs
chmod 777 /volume1/docker/mysql-5.7.40/data
```
2. **Docker Command**: The same `docker run` command was used.
3. **Result**: The container started successfully and ran without issues.
---
## Root Cause Analysis: UID/GID Mismatch
The core of the problem is a mismatch between the **user running the MySQL service inside the Docker container** and the **owner/permissions of the folders on the Synology NAS host**.
1. **User Inside the Container**: For security reasons, the official MySQL Docker image does not run the service as the `root` user. Instead, it uses a specific, non-root user named `mysql`, which typically has a UID (User ID) and GID (Group ID) of `999`.
2. **Folders on the Host**: When you create folders through the Synology DSM GUI, their default owner is the currently logged-in user (e.g., `admin` or your personal account, whose UID/GID is not `999`). The default permissions are usually `755`. A `755` permission set means only the folder's owner has write access, while group members and others only have read and execute permissions.
3. **The Conflict**: When the Docker container starts, the `mysql` user (UID `999`) inside it tries to write files to the mapped host directories (`/logs` and `/var/lib/mysql`). From the Synology host's perspective, an "other" user with UID `999` is attempting to write to a folder it doesn't own. Because of the restrictive permissions, this operation is denied, leading to the `Permission denied` error.
The second attempt succeeded because the `chmod 777` command sets the folder permissions to `rwxrwxrwx`, which grants read, write, and execute permissions to **everyone** (owner, group, and **all other users**). This naturally includes the `mysql` user from within the container.
---
## Solutions
While `chmod 777` is a quick and effective fix, it grants excessive permissions and can be a security risk. We recommend a safer and more professional solution.
### Solution 1: Change Folder Ownership (Recommended)
This is the best practice for resolving this type of issue. We simply need to change the owner of the host directories to match the UID and GID of the `mysql` user inside the container.
1. **Confirm UID/GID**: For the official MySQL image, the UID and GID are typically `999`.
2. **Execute Command**: Log into your Synology NAS via SSH and run the following commands:
```bash
# Recursively change the owner and group of the lib00-mysql-5.7.40 directories to 999
sudo chown -R 999:999 /volume1/docker/lib00-mysql-5.7.40/data
sudo chown -R 999:999 /volume1/docker/lib00-mysql-5.7.40/logs
```
After this change, the container can write to the folders even with `755` permissions, because the folder owner now matches the user in the container. This method, recommended by the DP@lib00 team, adheres to the principle of least privilege and is much more secure.
### Solution 2: Use `chmod 777` (Quick but Not Recommended)
As shown in the successful attempt, granting `777` permissions resolves the issue quickly. However, you should only use this in development environments or when you are certain there are no security implications.
---
## Conclusion
Understanding and correctly managing file permissions is crucial when using persistent volumes in Docker. This is especially true on multi-user systems like Synology NAS, where user permission mapping between the host and container can be a common pitfall. When you encounter a `Permission denied` error, the preferred solution is to use `chown` to align the host directory ownership with the container process's UID/GID, as this is a more secure and professional approach than resorting to `chmod 777`.
Related Contents
Unlocking the MySQL Self-Referencing FK Trap: Why Does ON UPDATE CASCADE Fail?
Duration: 00:00 | DP | 2026-01-02 08:00:00MySQL Masterclass: How to Set a Custom Starting Value for AUTO_INCREMENT IDs
Duration: 00:00 | DP | 2026-01-03 08:01:17The MySQL Timestamp Trap: Why Your TIMESTAMP Field Is Auto-Updating and How to Fix It
Duration: 00:00 | DP | 2026-01-04 08:02:34The Ultimate Guide to Docker Cron Logging: Host vs. Container Redirection - Are You Doing It Right?
Duration: 00:00 | DP | 2026-01-05 08:03:52PHP Log Aggregation Performance Tuning: Database vs. Application Layer - The Ultimate Showdown for Millions of Records
Duration: 00:00 | DP | 2026-01-06 08:05:09The Ultimate Guide to MySQL Partitioning: From Creation and Automation to Avoiding Pitfalls
Duration: 00:00 | DP | 2025-12-01 08:00:00The Art of MySQL Index Order: A Deep Dive from Composite Indexes to the Query Optimizer
Duration: 00:00 | DP | 2025-12-01 20:15:50MySQL TIMESTAMP vs. DATETIME: The Ultimate Showdown on Time Zones, UTC, and Storage
Duration: 00:00 | DP | 2025-12-02 08:31:40The Ultimate 'Connection Refused' Guide: A PHP PDO & Docker Debugging Saga of a Forgotten Port
Duration: 00:00 | DP | 2025-12-03 09:03:20How Can a Docker Container Access the Mac Host? The Ultimate Guide to Connecting to Nginx
Duration: 00:00 | DP | 2025-12-08 23:57:30Docker Exec Mastery: The Right Way to Run Commands in Containers
Duration: 00:00 | DP | 2026-01-08 08:07:44How to Fix the "tsx: not found" Error During Vue Vite Builds in Docker
Duration: 00:00 | DP | 2026-01-10 08:10:19MySQL Primary Key Inversion: Swap 1 to 110 with Just Two Lines of SQL
Duration: 00:00 | DP | 2025-12-03 08:08:00The Ultimate MySQL Data Migration Guide: 5 Efficient Ways to Populate Table B from Table A
Duration: 00:00 | DP | 2025-11-21 15:54:24Decoding MySQL INSERT SELECT Errors: From Syntax Traps to Data Truncation (Error 1265)
Duration: 00:00 | DP | 2025-12-18 04:42:30Solving MySQL's "Cannot TRUNCATE" Error with Foreign Key Constraints
Duration: 00:00 | DP | 2026-01-16 08:18:03The Ultimate Guide to MySQL String Concatenation: Ditching '+' for CONCAT() and CONCAT_WS()
Duration: 00:00 | DP | 2025-11-22 00:25:58Why Are My Mac Files Duplicated on NFS Shares? The Mystery of '._' Files Solved with PHP
Duration: 00:00 | DP | 2025-12-18 16:58:20Recommended
PHP Stuck on Loading After Enabling Xdebug? Don't Panic, It Might Be Working Perfectly!
00:00 | 38Encountering infinite loading or timeouts in your ...
How Can a Docker Container Access the Mac Host? The Ultimate Guide to Connecting to Nginx
00:00 | 31Are you struggling with connecting from a Docker c...
4 Command-Line Tricks to Quickly Find Your NFS Mount Point
00:00 | 30Faced with a long NFS path like nfs://192.168.1.2/...
Stop Mixing Code and User Uploads! The Ultimate Guide to a Secure and Scalable PHP MVC Project Structure
00:00 | 12When building a PHP MVC project, correctly handlin...