资讯动态

Docker实战避坑指南:从安装到微服务部署的完整经验总结

发布时间:2026/9/30 8:12:39 来源:尧图企业网站定制
搞Docker这几年踩过的坑比吃过的盐还多。尤其是帮同事和群友排查问题的时候发现大家问来问去翻来覆去就是那几类装不上、起不来、网络不通、权限报错。这玩意儿上手其实不难难的是你遇到的每一个报错都像一个“盲盒”不开你不知道里面装的是什么。这篇我不打算写成一个面面俱到的官方文档而是把日常用得最多、问得最狠的点串起来讲一遍从安装到排障从单容器到多容器编排从MySQL、Redis到微服务部署尽量把每一步背后的“为什么”也讲清楚。内容可能会有点长但你按着走一遍应该能少走很多弯路。1. 先搞清楚Docker到底解决什么问题1.1 用生活类比理解容器和镜像很多人学Docker第一反应是“虚拟机”。这个类比能帮你理解大概方向但容易把你带沟里去。虚拟机是模拟了一整台电脑CPU、内存、硬盘、网卡全部虚拟出来里面跑一个完整的操作系统。Docker不一样它直接共享宿主机的操作系统内核只是把应用程序及其依赖环境打包成一个“标准化集装箱”。我常用一个类比镜像就是“安装包”加“系统快照”的合体你用它创建出来的容器就是跑起来的“实例”。镜像就像做蛋糕的模具容器就是脱模出来的一块块蛋糕。模具可以反复使用蛋糕吃掉了重新做一个模具本身不会变。你改了容器里的东西比如装了个软件、改了配置文件镜像并不会跟着变除非你专门commit一个新镜像。这里有个新手最容易忽略的点容器是“无状态”的一删所有写入的文件全没了。所以凡是不能丢的数据比如MySQL的数据文件、Redis的持久化文件、应用的日志都必须通过挂载或卷的方式映射到宿主机上。很多人在容器里装完东西没搞两天被清了就是没搞明白这个逻辑。1.2 什么场景适合用Docker什么场景不适合Docker最适合的是“环境敏感型”应用。比如你本地跑Python 3.11线上是3.7一运行就崩或者你同时要给两三个项目提供不同版本的Node、Java用Docker可以一键起环境隔离得干干净净。反过来凡是需要高性能I/O裸设备操作、或者对内核模块有强依赖的场景比如数据库集群、GPU直通、高性能计算直接裸机可能更稳硬上Docker反而增加排障难度。还有一个场景是“快速体验”。比如你想试试某个开源项目又不想把宿主机搞脏直接docker run拉一个镜像跑起来用完就删干净利落。我在文章后面会专门讲几个这样的实战案例比如用Docker装MySQL 8.0、搭Redis主从、部署GitLab全部都是这个思路。2. 不同平台的安装与首启排障2.1 Windows上装Docker DesktopWSL2与虚拟化前置检查Windows装Docker官方推荐的就是Docker Desktop。但很多人在这一步就卡住了最常见的报错就是那句经典英文virtualization support not detected Docker Desktop failed to start because virtualization support is not enabled这句报错的字面意思是“检测不到虚拟化支持”。Docker Desktop在Windows上依赖两种后端之一Hyper-V或者WSL2而这两种都需要CPU的虚拟化功能VT-x/AMD-V在BIOS/UEFI中处于开启状态。所以遇到这个报错第一件事不是重新安装而是检查虚拟化开关。检查路径按顺序来打开任务管理器切到“性能”选项卡看右下角“虚拟化”字段是不是“已启用”。如果显示“已禁用”重启电脑进BIOS开机狂按Del或F2各品牌按键不同在CPU Configuration或Advanced下找到Intel Virtualization Technology / SVM Mode设为Enabled。打开控制面板“启用或关闭Windows功能”确保“虚拟机平台”和“适用于Linux的Windows子系统”两个选项被勾选。如果用的老电脑不支持虚拟化那就只能换Docker Toolbox这类老方案但说实话体验很差不如直接换Linux环境学习。还有一个小坑经常被忽略WSL2要求Windows 10 21H2以上内核版本要够新才稳。如果docker desktop安装后反复要求更新WSL内核去微软官网下最新的wsl_update_x64.msi手动装一遍即可。装完之后建议在PowerShell里跑一次wsl --set-default-version 2让分发版跑在WSL2模式性能比WSL1好太多。2.2 Ubuntu和CentOS上装Docker引擎Linux下安装相对清爽。Ubuntu这边我用的是官方apt源的方式sudo apt update sudo apt install -y ca-certificates curl gnupg sudo install -m 0755 -d /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg echo deb [arch$(dpkg --print-architecture) signed-by/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release echo $VERSION_CODENAME) stable | sudo tee /etc/apt/sources.list.d/docker.list /dev/null sudo apt update sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin这里解释一下为什么每一条命令都值得认真写gpg密钥和sources.list是两个独立的信任环节不装keyrings直接添加源apt会拒绝校验装一半报错率极高。而docker-compose-plugin这个包是Compose v2的官方插件形式以后写Compose编排少一个单独安装的麻烦。CentOS 7 / 8那边稍微不一样老系统还需要额外配置yum源。有些系统的默认源里没有docker-ce包需要先装yum-utils再用yum-config-manager --add-repo添加官方仓库。CentOS 7还有一个额外的坑默认的iptables规则会和Docker的NAT规则冲突偶尔会出现容器能起但网络不通的情况解决办法通常是在/etc/sysconfig/docker里追加OPTIONS--iptablesfalse但副作用是所有端口映射都要自己手工处理不推荐新手折腾能升CentOS 8或换Ubuntu就换。装完顺手把当前用户加进docker组省得每条命令都要sudosudo usermod -aG docker $USER newgrp docker注意退出重登一下才生效。2.3 Docker服务启动失败的几种典型情况Linux下启动Docker服务报错很多都不是Docker本身的问题而是cgroup驱动跟系统初始化系统不对付。最典型的一个报错是Failed to start docker.service: Unit docker.service not found.这个大概率是你安装的发行版仓库里根本没有docker-ce或者安装不完整。本质上不是“启动失败”而是“服务文件不存在”。优先检查apt list --installed | grep docker或rpm -qa | grep docker确认docker-ce这个包在不在。没在老老实实重新按2.2的步骤装一遍。另一种很常见的情况是服务启动时报apply_credentials security_opt fails或者failed to create NAT chain DOCKER。前者多半是系统开启了SELinux与容器网络命名空间冲突在/etc/selinux/config里把SELINUX改成permissive或者干脆关掉后者则是iptables规则被某个风控软件清掉导致DOCKER链丢失重启dockerd或者手动iptables -t nat -F后systemctl restart docker能恢复。Windows下还有那种failed to connect to the docker api at npipe:////./pipe/dockerdesktoplinuxen的报错我跟你说十有八九不是Docker坏了而是Docker Desktop引擎根本没起来。点开右下角鲸鱼图标等它变成稳定状态再说命令连上去是真的需要引擎在跑。3. 镜像加速配置与容器生命周期管理3.1 镜像源为什么要配置怎么配置很多人在拉镜像的时候发现下载特别慢甚至直接超时。这个问题的根源是官方镜像仓库Docker Hub的服务器在国外默认情况下你拉一个几GB的镜像可能要等半小时甚至更久。解决思路就是给dockerd配置镜像加速器本质上就是让它在拉镜像时走一条更快的路。在Linux上改这个文件sudo mkdir -p /etc/docker sudo tee /etc/docker/daemon.json -EOF { registry-mirrors: [https://docker.m.daocloud.io] } EOF sudo systemctl daemon-reload sudo systemctl restart docker然后验证一下生效docker info | grep -A 5 Registry Mirrors补充说明一点这个配置文件还有一个意外的好处就是统一放>{ registry-mirrors: [https://docker.m.daocloud.io], data-root: /data/docker, log-driver: json-file, log-opts: { max-size: 50m, max-file: 3 } }Docker Desktop的在图形界面配置路径是Settings - Docker Engine直接改里面的JSON就行。改完点Apply Restart。3.2 从拉镜像到跑容器的完整流程下面用一个最简单的Nginx来演示完整流程。这串命令我几乎每天都会敲docker pull nginx:alpine docker run -d --name my-nginx -p 8080:80 nginx:alpine这里有两个细节值得解释。-p 8080:80的含义是“宿主机的8080端口转发到容器内部的80端口”。8080可以随便改但80是Nginx默认监听端口改不了。访问http://localhost:8080能看到页面说明容器正常跑起来了。-d表示后台运行不加的话你的终端会直接挂在前台CtrlC一按容器就停了。调试阶段可以不加-d看日志方便确认没问题再改成后台模式。然后看看容器状态和日志docker ps -a docker logs my-nginxdocker ps -a和docker ps的区别-a连已经停止的容器也列出来。新手经常遇到“我明明创建了容器但docker ps看不到”就是漏了-a。3.3 常用命令速查与容器日志查看我整理了一张小表按使用频率排的背熟这张表基本能应付日常90%的操作命令作用备注docker ps -a列出所有容器含退出不加-a只看运行中的docker images列出本地镜像不带仓库名就是全部docker pull xxx拉取镜像等价于 docker image pulldocker run -d --name xxx -p 宿主机端口:容器端口 镜像创建并启动容器-d后台、-it交互docker exec -it xxx bash进入运行中容器的shell前提是容器里有bashdocker logs -f xxx跟踪容器日志-f是follow模式docker stop/start/restart xxx停止/启动/重启容器容器id或name均可docker rm -f xxx强制删除容器正在运行的容器也能删掉docker rmi xxx删除镜像有容器引用时会报错docker inspect xxx查看容器详细信息网络、挂载、entrypoint都在这docker logs -f这个命令我看好多人不会用。容器里如果跑的是Java等常驻进程日志全打到stdout和stderr不用进容器翻文件直接在宿主机上就能看。这一点比传统进程管理舒服太多。4. 实战那些高频使用的容器化部署方案4.1 MySQL 8.0数据目录与初始化密码MySQL在Docker里跑容易踩的坑挺有代表性的值得单独拆开讲。先看最基础的一条命令docker run -d --name mysql8 \ -p 3306:3306 \ -e MYSQL_ROOT_PASSWORDyourpassword \ -e MYSQL_DATABASEtestdb \ -v /data/mysql:/var/lib/mysql \ mysql:8.0关键环境变量是MYSQL_ROOT_PASSWORD容器初始化时会自动设置root密码这个密码在首次启动时生效。这里有个时间差问题容器刚start的时候MySQL还没有初始化完成如果你马上用客户端去连大概率会报“Access denied”或者“Cant connect”不是密码错而是服务还没真正就绪。常见的做法是等待几秒或者用docker logs mysql8 | grep ready for connections来确认初始化完毕。音量挂载那一块要格外重视-v /data/mysql:/var/lib/mysql的意思是宿主机上/data/mysql目录与容器内/var/lib/mysql目录共享MySQL数据文件会落在宿主机上。容器一删数据还在下次再跑一个新的mysql8容器指定同一个目录数据自动恢复。这是Docker持久化的基本逻辑不这么干的话容器删了数据就没了等于白跑。还有一个我反复跟人强调的坑MySQL 8.0的认证插件。8.0默认用的是caching_sha2_password一些旧版本的客户端工具比如Navicat 15以下连不上报错Authentication plugin caching_sha2_password cannot be loaded。解决办法是启动时追加--default-authentication-pluginmysql_native_password或者在容器里执行ALTER USER语句改认证方式个人建议用启动参数简单省事升级镜像后配置也不会丢。4.2 Redis从单机到主从Redis用Docker跑起来比MySQL简单多了但做主从复制时要小心一个坑容器内的Redis默认监听的是127.0.0.1让它对外提供服务的核心参数是--bind 0.0.0.0和--appendonly yes。先看单机版docker run -d --name redis \ -p 6379:6379 \ -v /data/redis:/data \ redis:7.0 --appendonly yes注意命令行的--appendonly yes是传给Redis进程的参数不是Docker参数位置要放在镜像名后面。Redis官方镜像的entrypoint会把镜像名后面的内容传给redis-server。很多人把参数写在-p前面结果Docker完全不认识直接报“unknown flag”。主从模式下主库命令不变从库加一个--replicaof参数docker run -d --name redis-slave \ -p 6380:6379 \ --link redis:master \ redis:7.0 --replicaof master 6379不过--link是老式做法的残留现在更推荐用自定义网络来保证容器间通信。我会在后面的网络章节专门讲。Redis主从模式下如果发现从库同步一直在重连多半是master容器没有绑定0.0.0.0从库连不上它的6379端口。用redis-cli进从库执行info replication看一下master_link_status就知道问题在哪。4.3 GitLab社区版和其他“偏门”部署GitLab社区版是我用Docker部署最重的应用之一。官方推荐用gitlab-omnibus镜像一条命令就能拉全套硬件配置要求不高但吃内存2GB内存起步跑起来才算流畅。docker run -d --name gitlab \ -p 8081:80 \ -p 8022:22 \ -v /data/gitlab/config:/etc/gitlab \ -v /data/gitlab/logs:/var/log/gitlab \ -v /data/gitlab/data:/var/opt/gitlab \ gitlab/gitlab-ce:latest启动之后用docker logs -f gitlab看进度第一次启动要等个三五分钟等出现gitlab Reconfigured!字样再去浏览器访问。这里有个非常容易踩的坑如果你把80端口映射到别的端口比如8081GitLab默认生成的仓库clone链接还是http://IP/group/repo.git不会自动带上端口。需要在/etc/gitlab/gitlab.rb里手动改external_urlexternal_url http://IP:8081改完重启容器让gitlab-ctl reconfigure生效。再看几个偏门但有实际应用场景的。比如用KodBox做个人网盘一条命令docker run -d --name kodbox \ -p 8088:80 \ -v /data/kodbox:/var/www/html \ kodbox/kodboxMetabase这种BI工具数据分析内部用挺好使docker run -d --name metabase \ -p 3000:3000 \ -e MB_DB_TYPEpostgres \ -e MB_DB_DBNAMEmetabase \ -e MB_DB_USERxxx \ -e MB_DB_PASSxxx \ metabase/metabaseMediamtx做流媒体转发很多智能家居和监控项目里会用到用Docker跑非常干净docker run -d --name mediamtx \ -p 8554:8554 \ -p 1935:1935 \ -p 8888:8888 \ bluenviron/mediamtx这类工具的共同特点是对宿主机污染极小删掉容器就像没装过一样环境变量、配置、数据全部通过参数和挂载管理比直接装二进制在系统上干净太多。4.4 用Docker跑Python环境的轻量方案这个场景在日常开发里比你想的更常见。项目A要Python 3.9项目B要3.11直接装系统全局必然打架。用Docker可以做到互不干扰docker run -it --rm \ -v $(pwd):/workspace \ -w /workspace \ python:3.11-slim bash这条命令会拉一个精简版Python 3.11镜像把当前目录挂载到容器内的/workspace并预先把工作目录切过去。在容器里执行python --version就能看到3.11版本跟宿主机环境完全隔离。如果项目依赖比较复杂建议直接用Dockerfile把依赖打包进镜像FROM python:3.11-slim WORKDIR /app COPY requirements.txt . RUN pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple COPY . . CMD [python, app.py]构建命令是docker build -t my-python-app .跑起来docker run -d --name my-app my-python-app。这种方式的好处是镜像里已经固定了依赖版本拿到任何一台装了Docker的机器都能一键跑彻底告别“在我电脑上是好的”这种问题。5. 网络与权限新手最容易卡住的环节5.1 端口映射与容器间通信Docker容器之间的通信我建议所有新手都直接养成用自定义桥接网络的习惯别用--link。Docker内置了三种网络模式bridge默认、host、none。你手动创建的网络也属于bridge但它自带了DNS解析能力容器之间可以通过容器名直接互访这一点是默认bridge网络做不到的。创建网络的命令docker network create app-net跑容器的时候指定网络docker run -d --name mysql8 --network app-net -p 3306:3306 mysql:8.0 docker run -d --name backend --network app-net -p 8080:8080 my-backend这样backend容器里访问mysql8:3306就能直连数据库不需要通过宿主机IP转发。如果走默认bridge网络容器名解析会时不时失效测试环境还好生产环境你会被这个不稳定搞得怀疑人生。5.2 网络不通的排查顺序容器网络不通是我被问得最多的一类问题。有人直接说“Docker网络不通”我通常会让对方按下面这个顺序排查容器能不能访问外网docker exec -it 容器名 ping baidu.com。不能先看宿主机能不能上网再看DNS配置最后查iptables。容器之间能不能互访进入容器A ping容器B的容器名或IP。能通说明网络配置没问题不通重点查自定义网络是否正常。宿主机能不能访问容器端口直接在宿主机上curl localhost:映射端口。不通检查映射端口是不是没写对或者容器内应用实际监听的端口与你以为的不一致。外部机器能不能访问这一步往往是安全组、防火墙拦截跟Docker本身关系不大。顺便说一个特别隐蔽的坑容器内应用监听地址是127.0.0.1。比如你在容器里跑了一个服务它默认只监听容器自己的回环地址宿主机转发过去的请求根本到不了它。排查方法是在容器里执行ss -tlnp看监听地址如果都是127.0.0.1开头的把应用配置改成0.0.0.0。5.3 权限错误与挂载目录的坑Docker权限错误最常见的就是这句Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock这个问题的根源是当前用户不在docker组里。不加sudo执行docker命令时sock文件的权限校验就会失败。解决办法我在前面Linux安装章节已经给过usermod -aG docker $USER然后重新登录。如果你不想重新登录可以用newgrp docker让当前shell直接生效。挂载目录的坑则更隐蔽。很多人在容器里看到挂载目录权限不对、文件不可写报Permission denied。多数情况不是Docker的问题而是挂载目录的属主和属组与容器内进程期望的不一致。比如MySQL容器内的mysql用户UID是999你宿主机上/data/mysql的属主是root容器内进程写不进去。解决办法是先把目录属主改成999chown -R 999:999 /data/mysql这一点在数据卷比较大的场景里特别重要写进部署脚本里能避免很多次半夜被叫起来。6. 进阶Compose编排与微服务部署6.1 Compose文件怎么写单容器用docker run还能凑合一旦涉及多容器关联docker run敲得手酸还容易写错参数。这种场景就该上Compose了。Compose的核心是YAML文件下面用“后端MySQLRedis”的典型组合来举例version: 3.8 services: mysql: image: mysql:8.0 container_name: app-mysql restart: always environment: MYSQL_ROOT_PASSWORD: root123 MYSQL_DATABASE: appdb volumes: - /data/mysql:/var/lib/mysql ports: - 3306:3306 networks: - app-net redis: image: redis:7.0 container_name: app-redis restart: always command: [--appendonly, yes] volumes: - /data/redis:/data networks: - app-net backend: image: my-backend:latest container_name: app-backend restart: always ports: - 8080:8080 depends_on: - mysql - redis networks: - app-net networks: app-net: driver: bridge启动方式一条命令docker compose up -d查看状态是docker compose ps强制重建是docker compose up -d --build整体拆除是docker compose down。down命令会清掉网络但外面挂载的数据卷还在这一点也算是个小优势重建后再up数据也不会丢。depends_on是个容易产生误解的配置。它只控制容器启动顺序不保证依赖服务“准备好了”。MySQL容器打印“ready for connections”之前backend容器可能已经在连数据库了于是连不上。成熟的方案是在应用启动脚本里加等待逻辑或者用类似wait-for-it.sh的工具先把依赖服务的TCP端口探测通再往后走。6.2 微服务项目部署的完整流程微服务用Docker部署本质上是把每个服务打成一个镜像再用Compose把所有服务编排起来。我以Spring Boot为例讲一下常见套路语言不是关键思路通用。流程一般是每个服务模块下写好Dockerfile然后通过CI或本地构建生成镜像推到私有仓库或者直接传tar包到服务器最后在服务器上docker compose up -d。我见过很多刚接触微服务部署的同学卡在“同一个项目拆成多个服务”这个环节上总想把所有服务塞进一个容器里。这种操作完全违背了容器的设计理念。一个容器一个主进程这才是Docker的哲学。如果后端、数据库、Redis全塞一起你根本没法独立升级、独立扩容还谈什么微服务。正确的做法是每个服务独立镜像、独立容器通过Compose或Kubernetes编排。服务的配置信息通过环境变量注入比如数据库连接串、Redis地址全部写进Compose文件的environment里这样容器在任何环境都跑得起来只要你换环境变量就行。配置抽离这一步做好了微服务部署就顺了。6.3 Java项目从IDEA打包镜像如果你主力是IntelliJ IDEA可以下载Docker插件直接在IDE里右键Dockerfile点击构建完事能一键push到仓库。命令行的方法更基本适合任何编辑器mvn clean package -DskipTests docker build -t my-service:1.0.0 . docker save my-service:1.0.0 | gzip my-service.tar.gz最后得到的tar包拷贝到服务器上docker load my-service.tar.gz docker compose up -d这里要提醒一点Dockerfile里不要把target目录整个COPY进去那里面有很多上一次构建的旧class和临时文件既拖慢构建又容易把脏东西带进镜像。正确姿势是用.dockerignore排除掉target目录、.git目录这类无关文件target/ .git/ .idea/ *.log Dockerfile这样构建时上下文体积能缩小好几个数量级特别是在网络上下文中构建时镜像推送和拉取都能快很多。6.4 用Docker跑一些开发测试工具的实战开发测试和教学场景里Docker也特别好使。很多漏洞靶场和安全测试工具都提供了现成镜像拉起即用宿主机不会留任何痕迹。比如DVWA靶场跑起来就是一条命令docker run -d --name dvwa \ -p 8085:80 \ vulnerables/web-dvwa等容器启动后浏览器访问http://localhost:8085它会展示出经典的PHPSQL环境用来学习常见的Web漏洞和防御手段非常合适。用完docker stop dvwa docker rm dvwa宿主机上干干净净。同样思路也适合跑机器人平台和边缘设备的开发环境。比如ROS2 Humble的开发镜像配合micro-ROS agent用作设备间通信调试这比在宿主机上手工编译ROS2环境省事得多。容器内跑Ubuntu ROS2容器外通过共享网络与外设通信整套开发环境可以在几台设备间快速复制。这类“用完即走”的容器化方式是我个人最喜欢的Docker用法之一。你不用为了一个测试需求给宿主机装一堆依赖库也不用担心测试环境的脏数据污染正式环境。Docker最核心的价值就是这个“环境隔离”能力。7. 常见问题速查表与整体经验小结我把高频问题整理成一张速查表方便收藏使用。遇到问题先查表表中没有的场景再用docker inspect分析能省大量时间。现象可能原因解决思路Docker Desktop启动失败提示virtualization support not detectedBIOS虚拟化未开启或Windows功能未启用BIOS打开VT-x/AMD-V勾选虚拟机平台和WSL2failed to connect to the docker api at npipe:////./pipe/dockerdesktoplinuxenDocker Desktop引擎未启动或重启不完整等待鲸鱼图标变稳定后重试或右键重启Got permission denied connecting to docker.sock当前用户不在docker组usermod -aG docker $USER重新登录Nginx/其他容器能启动但访问不了端口映射错、容器内监听地址为127.0.0.1、宿主机防火墙拦截依次检查docker ps端口、容器内ss -tlnp、systemctl status firewalldMySQL容器初始化失败数据目录权限不对或已有数据版本冲突chown -R 999:999 数据目录避免新旧版本混跑Redis主从不同步主库没绑0.0.0.0或从库无法解析主库主机名主库加--bind 0.0.0.0主从放同一网络用容器名互访镜像拉取超时/极慢网络到Docker Hub不稳定配置registry-mirrors或者预下载镜像tar包离线导入容器重启后数据丢失没有挂载数据卷把持久化目录通过-v映射到宿主机Docker启动时iptables报错宿主机的iptables规则被外部工具清掉或与SELinux冲突iptables -t nat -F后重启docker调整SELinux策略最后再分享一个小技巧是我最近特别喜欢用的排查任何容器问题前先查三个地方——状态、日志、环境变量。docker ps -a看状态docker logs --tail 100 容器名看最近日志docker inspect 容器名 | grep -A 5 Environment看配置。90%的问题在这三步之内就能定位。不要一上来就想着重装Docker或重建容器先看日志多花一分钟能省半小时。还有一点尤其想对新手说Docker的命令背得再熟也不如理解它背后的逻辑来得重要。镜像和容器的关系、数据卷的持久化、网络模式的差异这三件事想明白哪怕命令忘了查一下帮助就能用起来。反过来只记命令不理解原理换个场景就抓瞎。我自己带过不少新人凡是在这三件事上肯花时间的后面上手都特别快。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑