Skip to content

Commit d4b15fc

Browse files
tac0turtleclaude
andcommitted
docs: add migration guide for non-root Docker containers
Covers bind mounts, named volumes, Kubernetes init containers, fsGroup, and docker-compose. Links from the changelog entry. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent f237083 commit d4b15fc

File tree

3 files changed

+117
-1
lines changed

3 files changed

+117
-1
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2121
### Changes
2222

2323
- Store pending blocks separately from executed blocks key. [#3073](https://github.com/evstack/ev-node/pull/3073)
24-
- **BREAKING:** Docker images for `evm`, `testapp`, and `local-da` now run as non-root user `ev-node` (uid 1000) instead of `root`. Existing volumes or bind mounts with root-owned files may require a `chown` to uid 1000.
24+
- **BREAKING:** Docker images for `evm`, `testapp`, and `local-da` now run as non-root user `ev-node` (uid 1000) instead of `root`. Existing volumes or bind mounts with root-owned files may require a `chown` to uid 1000. See the [migration guide](https://ev.xyz/guides/migrate-docker-nonroot).
2525

2626
## v1.0.0-rc.4
2727

docs/.vitepress/config.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,10 @@ function sidebarHome() {
305305
text: "Migrating to ev-abci",
306306
link: "/guides/migrating-to-ev-abci",
307307
},
308+
{
309+
text: "Migrate Docker to non-root",
310+
link: "/guides/migrate-docker-nonroot",
311+
},
308312
{
309313
text: "Create genesis for your chain",
310314
link: "/guides/create-genesis",
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
# Migrating Docker Containers to Non-Root User
2+
3+
Starting with this release, the `evm`, `testapp`, and `local-da` Docker images run as a non-root user (`ev-node`, uid/gid 1000) instead of `root`. This aligns with the `grpc` image, which already ran as non-root.
4+
5+
If you are running any of these containers with **persistent volumes or bind mounts**, you need to fix file ownership before upgrading. Containers running without persistent storage (ephemeral) require no action.
6+
7+
## Who is affected
8+
9+
You are affected if **all** of the following are true:
10+
11+
- You run `evm`, `testapp`, or `local-da` via Docker (or docker-compose / Kubernetes)
12+
- You use a volume or bind mount for the container's data directory
13+
- The files in that volume were created by a previous (root-based) image
14+
15+
## Migration steps
16+
17+
### 1. Stop the running container
18+
19+
```bash
20+
docker stop <container-name>
21+
```
22+
23+
### 2. Fix file ownership on the volume
24+
25+
For **bind mounts** (host directory), run `chown` directly on the host:
26+
27+
```bash
28+
# Replace /path/to/data with your actual data directory
29+
sudo chown -R 1000:1000 /path/to/data
30+
```
31+
32+
For **named Docker volumes**, use a temporary container:
33+
34+
```bash
35+
# Replace <volume-name> with your Docker volume name
36+
docker run --rm -v <volume-name>:/data alpine chown -R 1000:1000 /data
37+
```
38+
39+
### 3. Pull the new image and restart
40+
41+
```bash
42+
docker pull <image>
43+
docker start <container-name>
44+
```
45+
46+
### Kubernetes / docker-compose
47+
48+
If you manage containers through orchestration, you have two options:
49+
50+
**Option A: Init container (recommended for Kubernetes)**
51+
52+
Add an init container that fixes ownership before the main container starts:
53+
54+
```yaml
55+
initContainers:
56+
- name: fix-permissions
57+
image: alpine:3.22
58+
command: ["chown", "-R", "1000:1000", "/home/ev-node"]
59+
volumeMounts:
60+
- name: data
61+
mountPath: /home/ev-node
62+
securityContext:
63+
runAsUser: 1000
64+
runAsGroup: 1000
65+
fsGroup: 1000
66+
```
67+
68+
**Option B: Set `fsGroup` in the pod security context**
69+
70+
If your volume driver supports it, setting `fsGroup: 1000` will automatically fix ownership on mount:
71+
72+
```yaml
73+
securityContext:
74+
runAsUser: 1000
75+
runAsGroup: 1000
76+
fsGroup: 1000
77+
```
78+
79+
**docker-compose**: update your `docker-compose.yml` to set the user:
80+
81+
```yaml
82+
services:
83+
evm:
84+
image: evm:latest
85+
user: "1000:1000"
86+
volumes:
87+
- evm-data:/home/ev-node
88+
```
89+
90+
## Verifying the migration
91+
92+
After restarting, confirm the container runs as the correct user:
93+
94+
```bash
95+
docker exec <container-name> id
96+
# Expected: uid=1000(ev-node) gid=1000(ev-node)
97+
```
98+
99+
Check that the process can read and write its data directory:
100+
101+
```bash
102+
docker exec <container-name> ls -la /home/ev-node
103+
# All files should be owned by ev-node:ev-node
104+
```
105+
106+
## Troubleshooting
107+
108+
| Symptom | Cause | Fix |
109+
|---|---|---|
110+
| `Permission denied` on startup | Volume files still owned by root | Re-run the `chown` step above |
111+
| Container exits immediately | Data directory not writable | Check ownership and directory permissions (`drwxr-xr-x` or more permissive for uid 1000) |
112+
| Application writes to wrong path | Old `WORKDIR` was `/root` or `/apps` | Update any custom volume mounts to target `/home/ev-node` instead |

0 commit comments

Comments
 (0)