Linux搭建Docker私有倉庫的方法步驟
引言
在現(xiàn)代 DevOps 和云原生架構(gòu)中,Docker 已成為容器化部署的事實(shí)標(biāo)準(zhǔn)。而隨著企業(yè)規(guī)模擴(kuò)大和安全合規(guī)要求提升,搭建私有 Docker 倉庫(Private Docker Registry)已成為剛需。本文將從零開始,手把手教你如何在 Linux 系統(tǒng)上搭建一個功能完整、安全可靠、支持 HTTPS 和用戶認(rèn)證的私有鏡像倉庫,并提供 Java 客戶端操作示例。
一、為什么需要私有 Docker 倉庫?
雖然 Docker Hub 提供了海量公開鏡像,但在生產(chǎn)環(huán)境中,我們通常面臨以下問題:
- 安全性:業(yè)務(wù)鏡像包含敏感代碼或配置,不適合上傳到公有平臺。
- 網(wǎng)絡(luò)延遲:從海外拉取鏡像速度慢,影響 CI/CD 效率。
- 版本控制:需對鏡像進(jìn)行精細(xì)的版本管理和生命周期管理。
- 合規(guī)審計:企業(yè)需滿足數(shù)據(jù)不出內(nèi)網(wǎng)、鏡像可追溯等合規(guī)要求。
私有倉庫 = 鏡像存儲 + 訪問控制 + 日志審計 + 高可用部署
二、環(huán)境準(zhǔn)備
2.1 系統(tǒng)要求
- Linux 發(fā)行版:Ubuntu 20.04+ / CentOS 7+ / Rocky Linux 8+
- Docker Engine:20.10+
- Docker Compose:v2.0+
- 至少 2GB 內(nèi)存
- 開放端口:5000(默認(rèn) registry)、443(HTTPS)、80(HTTP重定向)
# 檢查 Docker 版本 docker --version # Docker version 24.0.5, build ced0996 # 檢查 Docker Compose docker compose version # Docker Compose version v2.20.2
2.2 域名與證書準(zhǔn)備(可選但推薦)
為啟用 HTTPS,你需要:
- 一個域名(如
registry.yourcompany.com) - SSL 證書(可使用 Let’s Encrypt 免費(fèi)證書)
推薦使用 Let’s Encrypt 獲取免費(fèi)證書。
三、基礎(chǔ)版:無認(rèn)證本地倉庫
最簡單的私有倉庫只需一條命令:
docker run -d \ -p 5000:5000 \ --restart=always \ --name local-registry \ -v /opt/registry/data:/var/lib/registry \ registry:2
啟動后,即可推送本地鏡像:
# 標(biāo)記鏡像 docker tag myapp:latest localhost:5000/myapp:latest # 推送鏡像 docker push localhost:5000/myapp:latest # 拉取鏡像 docker pull localhost:5000/myapp:latest
注意:此方式僅適用于測試環(huán)境!無認(rèn)證、無加密、無日志!
四、進(jìn)階版:帶用戶認(rèn)證的私有倉庫
4.1 創(chuàng)建 htpasswd 用戶文件
首先安裝 httpd-tools 或 apache2-utils:
# Ubuntu/Debian sudo apt update && sudo apt install apache2-utils -y # CentOS/RHEL sudo yum install httpd-tools -y
創(chuàng)建用戶密碼文件:
mkdir -p /opt/registry/auth htpasswd -Bbn admin P@ssw0rd > /opt/registry/auth/htpasswd htpasswd -Bbn devuser dev123 >> /opt/registry/auth/htpasswd
4.2 使用 docker-compose 編排服務(wù)
創(chuàng)建 docker-compose.yml:
version: '3.8'
services:
registry:
image: registry:2
restart: always
ports:
- "5000:5000"
environment:
REGISTRY_AUTH: htpasswd
REGISTRY_AUTH_HTPASSWD_REALM: Registry Realm
REGISTRY_AUTH_HTPASSWD_PATH: /auth/htpasswd
REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /data
volumes:
- /opt/registry/data:/data
- /opt/registry/auth:/auth
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"啟動服務(wù):
docker compose up -d
4.3 測試登錄與推送
# 登錄私有倉庫
docker login localhost:5000
# 輸入用戶名 admin,密碼 P@ssw0rd
# 標(biāo)記并推送
docker tag nginx:alpine localhost:5000/nginx:test
docker push localhost:5000/nginx:test
# 查看已推送鏡像
curl -u admin:P@ssw0rd http://localhost:5000/v2/_catalog
# {"repositories":["nginx"]}
五、企業(yè)級:HTTPS + 域名 + Nginx 反向代理
為了生產(chǎn)環(huán)境安全,必須啟用 HTTPS。
5.1 準(zhǔn)備 SSL 證書
假設(shè)你已申請好證書:
/etc/letsencrypt/live/registry.yourcompany.com/fullchain.pem/etc/letsencrypt/live/registry.yourcompany.com/privkey.pem
如果沒有,可通過 certbot 申請:
sudo certbot certonly --standalone -d registry.yourcompany.com
5.2 配置 Nginx 反向代理
創(chuàng)建 /etc/nginx/sites-available/docker-registry:
upstream docker-registry {
server 127.0.0.1:5000;
}
server {
listen 80;
server_name registry.yourcompany.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name registry.yourcompany.com;
ssl_certificate /etc/letsencrypt/live/registry.yourcompany.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/registry.yourcompany.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
client_max_body_size 0;
chunked_transfer_encoding on;
location / {
proxy_pass http://docker-registry;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 900;
}
}啟用配置并重啟 Nginx:
sudo ln -s /etc/nginx/sites-available/docker-registry /etc/nginx/sites-enabled/ sudo nginx -t && sudo systemctl reload nginx
5.3 修改 docker-compose.yml 支持外部訪問
version: '3.8'
services:
registry:
image: registry:2
restart: always
environment:
REGISTRY_AUTH: htpasswd
REGISTRY_AUTH_HTPASSWD_REALM: Registry Realm
REGISTRY_AUTH_HTPASSWD_PATH: /auth/htpasswd
REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /data
REGISTRY_HTTP_HOST: https://registry.yourcompany.com
REGISTRY_HTTP_SECRET: your_strong_secret_here_$(openssl rand -hex 32)
volumes:
- /opt/registry/data:/data
- /opt/registry/auth:/auth
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"REGISTRY_HTTP_SECRET 是用于簽名會話的密鑰,建議每次部署隨機(jī)生成。
六、監(jiān)控與日志管理
6.1 啟用訪問日志
Registry 默認(rèn)記錄 JSON 格式日志,可通過以下命令查看:
docker logs -f registry_registry_1
輸出示例:
{
"go.version": "go1.19.4",
"http.request.host": "registry.yourcompany.com",
"http.request.id": "a1b2c3d4-e5f6-7890-g1h2-i3j4k5l6m7n8",
"http.request.method": "GET",
"http.request.remoteaddr": "203.0.113.42",
"http.request.uri": "/v2/",
"http.request.useragent": "docker/24.0.5 go/go1.20.7 git-commit/ced0996 kernel/5.15.0-76-generic os/linux arch/amd64",
"level": "info",
"msg": "response completed",
"time": "2024-05-20T10:00:00Z"
}6.2 集成 Prometheus 監(jiān)控
修改 docker-compose.yml 添加監(jiān)控端點(diǎn):
environment: REGISTRY_HTTP_DEBUG_ADDR: :5001 REGISTRY_HTTP_DEBUG_PROMETHEUS_ENABLED: true REGISTRY_HTTP_DEBUG_PROMETHEUS_PATH: /metrics
然后通過 Prometheus 抓取 http://registry:5001/metrics。
七、Java 客戶端操作私有倉庫示例
雖然 Docker CLI 是主要操作工具,但在自動化系統(tǒng)、CI/CD 平臺中,常需通過程序調(diào)用 Registry API。下面是一個基于 Java + Apache HttpClient 的完整示例。
7.1 Maven 依賴
<dependencies>
<dependency>
<groupId>org.apache.httpcomponents.client5</groupId>
<artifactId>httpclient5</artifactId>
<version>5.2.1</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.15.2</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>2.0.7</version>
</dependency>
</dependencies>7.2 Java 客戶端類實(shí)現(xiàn)
import org.apache.hc.client5.http.classic.methods.*;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager;
import org.apache.hc.core5.http.*;
import org.apache.hc.core5.http.io.entity.EntityUtils;
import org.apache.hc.core5.http.message.BasicHeader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
public class DockerRegistryClient {
private static final Logger logger = LoggerFactory.getLogger(DockerRegistryClient.class);
private final String baseUrl;
private final String username;
private final String password;
private final CloseableHttpClient httpClient;
public DockerRegistryClient(String baseUrl, String username, String password) {
this.baseUrl = baseUrl.endsWith("/") ? baseUrl : baseUrl + "/";
this.username = username;
this.password = password;
PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
cm.setMaxTotal(100);
cm.setDefaultMaxPerRoute(20);
this.httpClient = HttpClients.custom()
.setConnectionManager(cm)
.build();
}
private String getAuthHeader() {
String credentials = username + ":" + password;
String encoded = Base64.getEncoder().encodeToString(credentials.getBytes(StandardCharsets.UTF_8));
return "Basic " + encoded;
}
public boolean ping() {
try {
HttpGet request = new HttpGet(baseUrl + "v2/");
request.addHeader("Authorization", getAuthHeader());
ClassicHttpResponse response = httpClient.executeOpen(null, request, null);
int status = response.getCode();
EntityUtils.consume(response.getEntity());
return status == 200 || status == 401; // 401 表示需要認(rèn)證,說明服務(wù)可達(dá)
} catch (Exception e) {
logger.error("Failed to ping registry", e);
return false;
}
}
public String listRepositories() throws IOException {
HttpGet request = new HttpGet(baseUrl + "v2/_catalog");
request.addHeader("Authorization", getAuthHeader());
try (ClassicHttpResponse response = httpClient.executeOpen(null, request, null)) {
if (response.getCode() != 200) {
throw new IOException("HTTP " + response.getCode() + ": " + response.getReasonPhrase());
}
String body = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
logger.info("Repositories: {}", body);
return body;
}
}
public String listTags(String repository) throws IOException {
HttpGet request = new HttpGet(baseUrl + "v2/" + repository + "/tags/list");
request.addHeader("Authorization", getAuthHeader());
try (ClassicHttpResponse response = httpClient.executeOpen(null, request, null)) {
if (response.getCode() != 200) {
throw new IOException("HTTP " + response.getCode() + ": " + response.getReasonPhrase());
}
String body = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
logger.info("Tags for {}: {}", repository, body);
return body;
}
}
public void deleteTag(String repository, String reference) throws IOException {
// 獲取 manifest digest
String digest = getManifestDigest(repository, reference);
if (digest == null) {
throw new IOException("Manifest not found for " + repository + ":" + reference);
}
HttpDelete request = new HttpDelete(baseUrl + "v2/" + repository + "/manifests/" + digest);
request.addHeader("Authorization", getAuthHeader());
request.addHeader("Accept", "application/vnd.docker.distribution.manifest.v2+json");
try (ClassicHttpResponse response = httpClient.executeOpen(null, request, null)) {
int code = response.getCode();
if (code == 202) {
logger.info("Successfully deleted {}@{}", repository, reference);
} else {
throw new IOException("HTTP " + code + ": " + response.getReasonPhrase());
}
}
}
private String getManifestDigest(String repository, String reference) throws IOException {
HttpHead request = new HttpHead(baseUrl + "v2/" + repository + "/manifests/" + reference);
request.addHeader("Authorization", getAuthHeader());
request.addHeader("Accept", "application/vnd.docker.distribution.manifest.v2+json");
try (ClassicHttpResponse response = httpClient.executeOpen(null, request, null)) {
Header digestHeader = response.getFirstHeader("Docker-Content-Digest");
return digestHeader != null ? digestHeader.getValue() : null;
}
}
public void close() throws IOException {
httpClient.close();
}
// 示例主函數(shù)
public static void main(String[] args) {
String registryUrl = "https://registry.yourcompany.com";
String user = "admin";
String pass = "P@ssw0rd";
try (DockerRegistryClient client = new DockerRegistryClient(registryUrl, user, pass)) {
System.out.println("?? Ping Registry: " + client.ping());
System.out.println("\n?? Repositories:");
client.listRepositories();
System.out.println("\n??? Tags for 'myapp':");
client.listTags("myapp");
// 刪除示例(謹(jǐn)慎使用)
// client.deleteTag("myapp", "old-tag");
} catch (Exception e) {
e.printStackTrace();
}
}
}7.3 輸出示例
運(yùn)行上述程序,你將看到類似輸出:
?? Ping Registry: true
?? Repositories:
{"repositories":["myapp","nginx","redis"]}
??? Tags for 'myapp':
{"name":"myapp","tags":["latest","v1.0","v1.1"]}此客戶端支持:
- 倉庫連通性檢測
- 列出所有倉庫
- 列出指定倉庫的所有標(biāo)簽
- 刪除指定鏡像標(biāo)簽(需開啟 delete 功能)
八、性能優(yōu)化與高可用部署
8.1 存儲驅(qū)動選擇
Registry 支持多種存儲后端:
filesystem(默認(rèn),適合單機(jī))s3(AWS S3 或兼容對象存儲)azure(Azure Blob Storage)gcs(Google Cloud Storage)swift(OpenStack Swift)
示例:使用 MinIO S3 兼容存儲
environment: REGISTRY_STORAGE: s3 REGISTRY_STORAGE_S3_ACCESSKEY: minio_access_key REGISTRY_STORAGE_S3_SECRETKEY: minio_secret_key REGISTRY_STORAGE_S3_REGION: us-east-1 REGISTRY_STORAGE_S3_BUCKET: docker-registry REGISTRY_STORAGE_S3_REGIONENDPOINT: http://minio:9000 REGISTRY_STORAGE_S3_ENCRYPT: "false" REGISTRY_STORAGE_S3_SECURE: "false"
8.2 啟用緩存層
使用 Redis 緩存頻繁訪問的元數(shù)據(jù):
environment:
REGISTRY_CACHE_BLOBDESCRIPTOR: redis
REGISTRY_REDIS_ADDR: redis:6379
REGISTRY_REDIS_DB: 0
REGISTRY_REDIS_POOL_MAXIDLE: 16
REGISTRY_REDIS_POOL_MAXACTIVE: 64
REGISTRY_REDIS_POOL_TIMEOUT: 300s
services:
redis:
image: redis:7-alpine
restart: always
volumes:
- redis-data:/data
volumes:
redis-data:8.3 負(fù)載均衡與多節(jié)點(diǎn)部署

所有節(jié)點(diǎn)共享同一存儲后端和緩存,確保數(shù)據(jù)一致性。
九、CI/CD 集成示例(Jenkins + Shell)
在 Jenkins Pipeline 中集成私有倉庫推送:
pipeline {
agent any
environment {
REGISTRY_URL = "registry.yourcompany.com"
REGISTRY_CRED = credentials('docker-registry-creds') // Jenkins Credentials ID
IMAGE_NAME = "myapp"
IMAGE_TAG = "${BUILD_NUMBER}-${env.GIT_COMMIT.take(8)}"
}
stages {
stage('Build') {
steps {
sh 'docker build -t ${IMAGE_NAME}:${IMAGE_TAG} .'
}
}
stage('Login & Push') {
steps {
sh '''
echo "$REGISTRY_CRED_PSW" | docker login $REGISTRY_URL -u "$REGISTRY_CRED_USR" --password-stdin
docker tag ${IMAGE_NAME}:${IMAGE_TAG} $REGISTRY_URL/${IMAGE_NAME}:${IMAGE_TAG}
docker push $REGISTRY_URL/${IMAGE_NAME}:${IMAGE_TAG}
docker logout $REGISTRY_URL
'''
}
}
stage('Cleanup') {
steps {
sh 'docker rmi ${IMAGE_NAME}:${IMAGE_TAG} $REGISTRY_URL/${IMAGE_NAME}:${IMAGE_TAG}'
}
}
}
post {
success {
echo "? Image pushed successfully: $REGISTRY_URL/$IMAGE_NAME:$IMAGE_TAG"
}
failure {
echo "? Build failed!"
}
}
}十、安全加固建議
10.1 啟用內(nèi)容信任(Notary)
Docker Content Trust(DCT)確保鏡像簽名和完整性:
export DOCKER_CONTENT_TRUST=1 export DOCKER_CONTENT_TRUST_SERVER=https://notary-server.yourcompany.com docker push registry.yourcompany.com/myapp:signed-v1
10.2 配置漏洞掃描(Clair / Trivy)
推薦使用 Trivy 掃描鏡像:
trivy image registry.yourcompany.com/myapp:latest
集成到 CI:
trivy image --exit-code 1 --severity CRITICAL registry.yourcompany.com/myapp:${IMAGE_TAG}
10.3 網(wǎng)絡(luò)隔離與防火墻
使用 firewalld 限制訪問源:
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.0/24" port protocol="tcp" port="5000" accept' sudo firewall-cmd --reload
十一、常見問題排查
Q1:unauthorized: authentication required
- 檢查是否執(zhí)行
docker login - 檢查 htpasswd 文件權(quán)限:
chmod 644 /opt/registry/auth/htpasswd - 檢查環(huán)境變量拼寫:
REGISTRY_AUTH_HTPASSWD_PATH
Q2:http: server gave HTTP response to HTTPS client
Docker 默認(rèn)強(qiáng)制 HTTPS。若使用 HTTP,需在 /etc/docker/daemon.json 中添加:
{
"insecure-registries": ["registry.yourcompany.com:5000"]
}然后重啟 Docker:
sudo systemctl restart docker
Q3: 推送大鏡像失敗
調(diào)整 Nginx 和 Registry 的超時設(shè)置:
# Nginx 配置中增加 proxy_read_timeout 1200; proxy_send_timeout 1200;
# docker-compose.yml environment: REGISTRY_HTTP_TIMEOUT: 1200s
十二、擴(kuò)展功能:Web UI 管理界面
官方 Registry 不提供 Web 界面,可集成第三方 UI:
推薦項(xiàng)目:Portus 或 Harbor(推薦后者)
Harbor 是 CNCF 畢業(yè)項(xiàng)目,功能完整:
- 圖形化鏡像管理
- 多租戶權(quán)限控制
- 漏洞掃描集成
- Helm Chart 支持
- 審計日志
部署 Harbor 參考官方文檔:https://goharbor.io/docs/
Harbor = Registry + Clair + Notary + Portal + RBAC + Replication
十三、設(shè)計理念與架構(gòu)解析
Docker Registry V2 遵循 RESTful 設(shè)計,核心概念:
- Repository(倉庫):一組相關(guān)鏡像集合,如
library/nginx - Tag(標(biāo)簽):指向特定 Manifest 的別名,如
latest,v1.0 - Manifest(清單):描述鏡像結(jié)構(gòu)的 JSON 文件,包含層列表和配置
- Blob(層):實(shí)際的文件系統(tǒng)層,內(nèi)容尋址存儲(SHA256)

每次推送,Docker 客戶端會先上傳所有層(Blob),最后提交 Manifest。
十四、鏡像清理策略
Registry 默認(rèn)不自動清理,需手動或定時刪除。
14.1 啟用刪除功能
在 config.yml 或環(huán)境變量中啟用:
environment: REGISTRY_STORAGE_DELETE_ENABLED: "true"
14.2 使用 GC 清理未引用層
# 進(jìn)入容器 docker exec -it registry_registry_1 /bin/sh # 執(zhí)行垃圾回收(需停止寫入) registry garbage-collect /etc/docker/registry/config.yml
14.3 自動化清理腳本
#!/bin/bash
# cleanup-old-images.sh
REGISTRY_URL="https://registry.yourcompany.com"
USER="admin"
PASS="P@ssw0rd"
REPOS=$(curl -s -u $USER:$PASS $REGISTRY_URL/v2/_catalog | jq -r '.repositories[]')
for REPO in $REPOS; do
TAGS=$(curl -s -u $USER:$PASS $REGISTRY_URL/v2/$REPO/tags/list | jq -r '.tags[]')
COUNT=0
for TAG in $TAGS; do
((COUNT++))
if [ $COUNT -gt 10 ]; then
echo "??? Deleting $REPO:$TAG"
# 調(diào)用前面 Java 客戶端的 deleteTag 方法或使用 curl
DIGEST=$(curl -s -I -u $USER:$PASS -H "Accept: application/vnd.docker.distribution.manifest.v2+json" \
$REGISTRY_URL/v2/$REPO/manifests/$TAG | grep Docker-Content-Digest | cut -d' ' -f2 | tr -d '\r')
curl -X DELETE -u $USER:$PASS $REGISTRY_URL/v2/$REPO/manifests/$DIGEST
fi
done
done
# 觸發(fā) GC
docker exec registry_registry_1 registry garbage-collect /etc/docker/registry/config.yml
十五、總結(jié)
搭建私有 Docker 倉庫不是“一次性工程”,而是持續(xù)演進(jìn)的基礎(chǔ)設(shè)施。從最簡單的 registry:2 單容器部署,到支持 HTTPS、認(rèn)證、高可用、漏洞掃描的企業(yè)級方案,每一步都應(yīng)根據(jù)團(tuán)隊規(guī)模和安全需求逐步推進(jìn)。
本文提供的 Java 客戶端可無縫集成到你的運(yùn)維平臺、CI/CD 系統(tǒng)或鏡像管理后臺中,實(shí)現(xiàn)自動化鏡像生命周期管理。
記住幾個關(guān)鍵原則:
?? 安全第一 —— 強(qiáng)制 HTTPS + 認(rèn)證
?? 可觀測性 —— 日志 + 監(jiān)控 + 告警
?? 自動化 —— 自動構(gòu)建 + 自動掃描 + 自動清理
?? 標(biāo)準(zhǔn)化 —— 統(tǒng)一命名規(guī)范 + Tag 策略 + 多環(huán)境鏡像同步
現(xiàn)在,是時候告別 docker save/load 的原始時代,擁抱現(xiàn)代化的私有鏡像倉庫體系了!
下一步行動建議:
- 在測試環(huán)境部署基礎(chǔ)版
- 編寫 Java 客戶端連接測試
- 申請域名和證書升級 HTTPS
- 集成到 Jenkins/GitLab CI
- 設(shè)置定期鏡像清理任務(wù)
以上就是Linux搭建Docker私有倉庫的方法步驟的詳細(xì)內(nèi)容,更多關(guān)于Linux搭建Docker私有倉庫的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Ubuntu22.04系統(tǒng):fatal:?無法連接到?github.com
這篇文章主要介紹了Ubuntu22.04系統(tǒng):fatal:?無法連接到?github.com的相關(guān)資料,需要的朋友可以參考下2024-03-03
Linux服務(wù)器SSH客戶端連接目標(biāo)服務(wù)器失敗的解決方法
Linux服務(wù)器SSH客戶端連接目標(biāo)服務(wù)器失敗怎么辦?在出現(xiàn)問題時我們先用排除法查找原因,以下是根據(jù)幾種情況列出的解決方法,希望可以幫助到你,需要的朋友可以參考下2025-10-10
ubuntu 設(shè)置靜態(tài)IP的實(shí)現(xiàn)方法
這篇文章主要介紹了ubuntu 靜態(tài)IP的設(shè)定實(shí)現(xiàn)方法的相關(guān)資料,需要的朋友可以參考下2016-10-10

