这篇是我学 Linux 和 Docker 时的学习笔记,时间大约在 2021 年前后。
起因是项目做到一定程度后发现自己不会部署,只写了代码不知道怎么让它跑起来。开始是在云服务器上捣鼓,后来把一台闲置笔记本装了 CentOS7 做自己的”测试服务器”,顺便把 Linux 和 Docker 的基础一起补了。
文章内容比较杂,更像是操作记录,不是系统化的教程。留在这里主要方便自己翻阅。
Linux 常用命令速查 以下是日常最常用的那些,完整的 man page 还是要靠查文档。
文件操作 ls -la pwd cd ~ mkdir -p a/b/c cp -r src/ dst/ rm -rf dir / mv old new find . -name "*.log" -size +100M
文件查看 cat -n file.txt tail -f /var/log/syslog grep -r "keyword" ./ less file.txt
tail -f 是看应用日志最常用的命令,配合 grep 做过滤更好用:tail -f app.log | grep ERROR
进程与系统 ps -ef | grep java kill -9 <pid> top df -h du -sh /home/docker netstat -anp | grep 8080
服务管理 systemctl start nginx systemctl stop nginx systemctl restart nginx systemctl enable nginx systemctl status nginx
文件权限 chmod 755 script.sh chmod +x script.sh chown user:group file
压缩解压 tar -zcvf archive.tar.gz dir / tar -zxvf archive.tar.gz tar -zxvf archive.tar.gz -C /home/
Docker 安装 CentOS7 安装 Docker yum install -y yum-utils yum-config-manager \ --add-repo \ https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo yum makecache fast yum install docker-ce docker-ce-cli containerd.io systemctl start docker systemctl enable docker
配置镜像加速(必做,不然拉镜像很慢) sudo mkdir -p /etc/dockersudo tee /etc/docker/daemon.json <<-'EOF' { "registry-mirrors" : [ "https://mirror.ccs.tencentyun.com" , "http://hub-mirror.c.163.com" ], "bip" : "192.168.200.1/24" } EOFsudo systemctl daemon-reloadsudo systemctl restart docker
Docker 常用命令 docker images docker pull nginx:latest docker rmi nginx:latest docker build -t myapp:1.0 . docker run -d -p 8080:8080 --name myapp myapp:1.0 docker run --rm -it ubuntu bash docker ps docker ps -a docker stop myapp docker start myapp docker restart myapp docker rm myapp docker rm -f myapp docker logs -f myapp docker logs --tail 100 myapp docker exec -it myapp bash docker inspect myapp docker system prune -a
Dockerfile 基础 FROM openjdk:11 -jre-slimWORKDIR /app COPY target/myapp.jar app.jar EXPOSE 8080 ENTRYPOINT ["java" , "-jar" , "app.jar" ]
常用指令说明:
指令 说明 FROM指定基础镜像,每个 Dockerfile 必须有 WORKDIR设置工作目录(后续 RUN/COPY 的相对路径基准) COPY拷贝文件,不会解压 ADD类似 COPY,但能自动解压 .tar.gz 文件 RUN构建时执行命令(每条 RUN 产生一个镜像层,能合并尽量合并) ENV设置环境变量 EXPOSE声明容器监听端口(仅声明,实际映射还需要 -p) ENTRYPOINT容器启动时执行的命令 CMD容器启动默认命令(可被 docker run 末尾参数覆盖)
RUN 命令多了会导致镜像层数多、体积大,建议用 && 合并:
RUN yum update -y && yum install -y curl wget && yum clean all
Docker Compose 基础 适合在单机上启动多个关联容器(开发环境/测试环境常用)。
version: '3.8' services: mysql: image: mysql:8.0 container_name: mysql ports: - "3306:3306" volumes: - /mydata/mysql/data:/var/lib/mysql - /mydata/mysql/conf:/etc/mysql/conf.d environment: - MYSQL_ROOT_PASSWORD=your_password restart: always redis: image: redis:6.2 container_name: redis ports: - "6379:6379" volumes: - /mydata/redis/data:/data command: redis-server --appendonly yes restart: always app: image: myapp:1.0 container_name: myapp ports: - "8080:8080" depends_on: - mysql - redis restart: always
docker-compose up -d docker-compose down docker-compose ps docker-compose logs -f
depends_on 只控制启动顺序,不保证依赖服务已经”就绪”,如果 app 启动比 MySQL 快,仍然可能连接失败。生产环境建议在应用层做重连逻辑。
踩坑记录 1. 宿主机无法访问容器里的服务(网卡地址冲突) 现象 :curl http://127.0.0.1:8080 返回 Connection reset by peer
原因 :Docker 默认网桥 docker0 的 IP 与宿主机其他网卡地址冲突
修复步骤 :
sudo service docker stopsudo ip link set dev docker0 downsudo brctl delbr docker0 sudo iptables -t nat -F POSTROUTINGsudo brctl addbr docker0sudo ip addr add 192.168.200.1/24 dev docker0sudo ip link set dev docker0 up vi /etc/docker/daemon.json systemctl restart docker
2. Docker 映射端口后防火墙关了仍然能从外网访问 原因 :Docker 在 iptables 里直接写了规则(绕过了 firewalld),即使 firewalld 关了对应端口,Docker 映射的端口仍然对外开放。
iptables -nL DOCKER iptables -D DOCKER 2
更好的做法 :只暴露需要对外的端口,敏感服务(如 MySQL、Redis)不映射到公网 IP 或绑定 127.0.0.1:
docker run -p 127.0.0.1:3306:3306 --name mysql ...
3. 多次构建镜像后磁盘爆满(vfs Storage Driver 问题) 现象 :CI/CD 发版时构建失败,提示磁盘不足。查看发现 /home/docker/vfs 目录占用将近 200G。
原因 :Docker 的 Storage Driver 设置为了 vfs,此模式不使用 Copy-on-Write,每个镜像层都是完整副本,构建次数多了磁盘自然爆掉。
docker info | grep "Storage Driver"
解决 :
docker system prune -a vi /etc/docker/daemon.json systemctl restart docker
为什么同一批机器会有不同的 Storage Driver?后来发现是 Docker 版本差异导致的默认值不同(20.x 和 23.x 默认策略不同)。环境初始化脚本里固定 storage-driver 可以避免这类问题。
小结 折腾了大半年 Linux 和 Docker 之后,最大的感受是:Docker 解决的不是”会不会部署”的问题,解决的是”部署一致性”的问题 。
在没有 Docker 之前,测试环境和生产环境经常因为环境差异出 bug,有了 Docker 之后这类问题少了很多。虽然容器本身也会有坑,但那是更高层次的问题了。