嘿,大家好!今天咱们聊个运维圈的经典笑话:一个实习生上生产环境,直接给所有文件设成 777
权限,结果 SSH 都连不上了。这事儿听着好笑,但真碰上了就头疼了。咱们就从这个糗事儿出发,聊聊实习生上生产环境该咋给自己设权限,尤其是部署一个 Spring Boot 的 Docker 服务,到底得用哪些命令,咋做才靠谱。咱从最简单的想法开始,一步步推到现代化的方案,顺便看看简单方法有啥坑,再想想咋优化到主流水平。
最简单的想法:啥都给 777
假设你是那个实习生,刚拿到一台生产服务器,想部署个 Spring Boot 应用,跑在 Docker 里。你一琢磨,权限不够咋办?简单,直接全开:
bash
chmod -R 777 /app
这命令把 /app
目录下所有文件都改成读写执行随便来。然后你兴冲冲地跑 Docker:
bash
docker run -d -p 8080:8080 my-springboot-app
结果呢?服务倒是跑起来了,但问题大了------SSH 连不上,服务器直接"裸奔"。为啥?777
太猛了,连系统关键文件都被改了权限,SSH 服务依赖的配置可能都废了。这就是传说中的"777惨案"。
简单方法的坑在哪
这最原始的法子看着省事,但毛病不少:
- 安全炸了:所有人都能读写执行,别人随便改个文件,服务就挂了。
- 误伤系统 :
-R
是递归改,连不该动的系统文件都中招,SSH 挂掉只是开始。 - 没必要:部署 Spring Boot 压根不需要这么大权限,白白增加了风险。
这法子显然不行,得想想更靠谱的路子。实习生上生产环境,到底该给自己啥权限呢?
第一步改进:最小权限试试
咱们冷静下来,部署 Spring Boot 的 Docker 服务,到底需要啥?一般是:
- 放文件的目录(比如
/app
)得能写。 - Docker 得能跑,涉及
docker
命令的执行权限。 - 不能随便改系统文件。
那就别用 777
了,试试最小权限。比如你是用户 dev
,先建个目录:
bash
mkdir /app
chown dev:dev /app
chmod 700 /app
700
是啥意思?用户 dev
有读写执行(4+2+1=7),其他人啥权限都没。这样 /app
归你管,安全多了。然后写个 Dockerfile,把 Spring Boot 应用打包:
dockerfile
FROM openjdk:17
COPY target/myapp.jar /app/myapp.jar
WORKDIR /app
CMD ["java", "-jar", "myapp.jar"]
构建镜像:
bash
docker build -t my-springboot-app .
跑容器:
bash
docker run -d -p 8080:8080 -v /app:/app my-springboot-app
这里 -v
把宿主机的 /app
挂载到容器里,权限够用,服务也能跑。但你试了试,发现 Docker 报错:permission denied
。咋回事?原来 docker
命令需要 root 权限,你得加 sudo
:
bash
sudo docker run -d -p 8080:8080 -v /app:/app my-springboot-app
这下好了吧?服务跑起来了,权限也没乱给。但还是有点别扭,手动加 sudo
太麻烦,而且 /app
里文件的权限还得再调调。
再优化:贴近生产环境
光这样还不够,生产环境不会让你随便用 root 跑东西。主流做法是啥呢?得用个专门的用户管服务,别直接拿自己的账号干活。咱们再改改:
-
创建个服务用户,比如
springuser
:bashsudo useradd -m springuser sudo passwd springuser # 设置密码
-
把
/app
给这个用户:bashsudo mkdir /app sudo chown springuser:springuser /app sudo chmod 750 /app # 用户读写执行,组读执行
-
切换到
springuser
:bashsu - springuser
-
部署时,Docker 不一定需要 root,可以加到
docker
组:bashsudo usermod -aG docker springuser
退出再登录,
springuser
就能直接跑docker
命令了。
然后构建和运行还是那套:
bash
docker build -t my-springboot-app .
docker run -d -p 8080:8080 -v /app:/app my-springboot-app
这时候,/app
里文件的权限得再确认下。Spring Boot 的 jar 文件只需要读执行就够,改一下:
bash
chmod 550 /app/myapp.jar
550
是用户和组可读可执行(4+1),别人没权限。服务跑得稳,权限也没乱放。
逼近主流:自动化与规范化
这套手动操作已经比 777
强多了,但离现代运维还有距离。生产环境里,手动敲命令早淘汰了,主流方案是用 CI/CD 管道 和 容器编排。咋弄呢?
-
用 GitHub Actions 自动部署 :
- 写个 workflow,push 代码后自动构建镜像,推到 Docker Hub。
- SSH 到服务器,拉镜像跑容器。
-
Docker Compose 单机部署:
yamlversion: '3' services: app: image: my-springboot-app ports: - "8080:8080" volumes: - /app:/app user: "springuser"
跑起来:
bashdocker-compose up -d
-
Kubernetes 上集群:
- 定义个 Deployment,指定
securityContext
跑非 root 用户:
yamlapiVersion: apps/v1 kind: Deployment metadata: name: springboot-app spec: replicas: 3 selector: matchLabels: app: springboot template: metadata: labels: app: springboot spec: securityContext: runAsUser: 1000 # springuser 的 UID containers: - name: app image: my-springboot-app ports: - containerPort: 8080
- 定义个 Deployment,指定
这些方案权限控制更细,部署也自动化,实习生再也不用手忙脚乱了。
优化方向:向主流靠拢
从最初的 777
到现在,问题暴露了一堆。基于这个案例,优化得往这些方向走:
- 最小权限 :别乱给
777
,用750
、550
这种精准权限。 - 专用用户 :别拿 root 或个人账号跑服务,建个
springuser
专门干活。 - 组权限 :加到
docker
组,避免每次sudo
。 - 自动化部署:用 CI/CD 或 Docker Compose,少手动操作。
- 容器安全 :指定非 root 用户运行,像 Kubernetes 的
runAsUser
。
这些都是现代运维的标配。数字上也得准,比如 750
是 7(读写执行)+ 5(读执行)+ 0,不能写成 751
,不然 others 多了一份执行权限。