sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": [
"https://docker.m.daocloud.io",
"https://huecker.io",
"https://dockerhub.timeweb.cloud",
"https://noohub.ru"
]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
需要有一台国外服务器, 按下面添加 Nginx 配置即可,配置完成后,在 /etc/docker/daemon.json
中修改成你的域名,具体参考上方配置,然后重启 docker
server {
listen 443 ssl;
server_name 域名;
ssl_certificate 证书地址;
ssl_certificate_key 密钥地址;
proxy_ssl_server_name on; # 启用SNI
ssl_session_timeout 24h;
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256';
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
location / {
proxy_pass https://registry-1.docker.io; # Docker Hub 的官方镜像仓库
proxy_set_header Host registry-1.docker.io;
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_buffering off;
# 转发认证相关的头部
proxy_set_header Authorization $http_authorization;
proxy_pass_header Authorization;
# 对 upstream 状态码检查,实现 error_page 错误重定向
proxy_intercept_errors on;
# error_page 指令默认只检查了第一次后端返回的状态码,开启后可以跟随多次重定向。
recursive_error_pages on;
# 根据状态码执行对应操作,以下为301、302、307状态码都会触发
#error_page 301 302 307 = @handle_redirect;
error_page 429 = @handle_too_many_requests;
}
#处理重定向
location @handle_redirect {
resolver 1.1.1.1;
set $saved_redirect_location '$upstream_http_location';
proxy_pass $saved_redirect_location;
}
# 处理429错误
location @handle_too_many_requests {
proxy_set_header Host 替换为在CloudFlare Worker设置的域名; # 替换为另一个服务器的地址
proxy_pass http://替换为在CloudFlare Worker设置的域名;
proxy_set_header Host $http_host;
}
}
登录到 Cloudflare 控制台, 新建 worker, 在 worker.js 文件中输入以下代码, 注意需要自行修改代码中的域名
'use strict'
const hub_host = 'registry-1.docker.io'
const auth_url = 'https://auth.docker.io'
const workers_url = 'https://你的域名'
const workers_host = '你的域名'
const home_page_url = 'https://qninq.cn/file/html/dockerproxy.html'
/** @type {RequestInit} */
const PREFLIGHT_INIT = {
status: 204,
headers: new Headers({
'access-control-allow-origin': '*',
'access-control-allow-methods': 'GET,POST,PUT,PATCH,TRACE,DELETE,HEAD,OPTIONS',
'access-control-max-age': '1728000',
}),
}
/**
* @param {any} body
* @param {number} status
* @param {Object<string, string>} headers
*/
function makeRes(body, status = 200, headers = {}) {
headers['access-control-allow-origin'] = '*'
return new Response(body, {status, headers})
}
/**
* @param {string} urlStr
*/
function newUrl(urlStr) {
try {
return new URL(urlStr)
} catch (err) {
return null
}
}
addEventListener('fetch', e => {
const ret = fetchHandler(e)
.catch(err => makeRes('cfworker error:\n' + err.stack, 502))
e.respondWith(ret)
})
/**
* @param {FetchEvent} e
*/
async function fetchHandler(e) {
const getReqHeader = (key) => e.request.headers.get(key);
let url = new URL(e.request.url);
if (url.pathname === '/') {
// Fetch and return the home page HTML content with replacement
let response = await fetch(home_page_url);
let text = await response.text();
text = text.replace(/{workers_host}/g, workers_host);
return new Response(text, {
status: response.status,
headers: response.headers
});
}
if (url.pathname === '/token') {
let token_parameter = {
headers: {
'Host': 'auth.docker.io',
'User-Agent': getReqHeader("User-Agent"),
'Accept': getReqHeader("Accept"),
'Accept-Language': getReqHeader("Accept-Language"),
'Accept-Encoding': getReqHeader("Accept-Encoding"),
'Connection': 'keep-alive',
'Cache-Control': 'max-age=0'
}
};
let token_url = auth_url + url.pathname + url.search
return fetch(new Request(token_url, e.request), token_parameter)
}
url.hostname = hub_host;
let parameter = {
headers: {
'Host': hub_host,
'User-Agent': getReqHeader("User-Agent"),
'Accept': getReqHeader("Accept"),
'Accept-Language': getReqHeader("Accept-Language"),
'Accept-Encoding': getReqHeader("Accept-Encoding"),
'Connection': 'keep-alive',
'Cache-Control': 'max-age=0'
},
cacheTtl: 3600
};
if (e.request.headers.has("Authorization")) {
parameter.headers.Authorization = getReqHeader("Authorization");
}
let original_response = await fetch(new Request(url, e.request), parameter)
let original_response_clone = original_response.clone();
let original_text = original_response_clone.body;
let response_headers = original_response.headers;
let new_response_headers = new Headers(response_headers);
let status = original_response.status;
if (new_response_headers.get("Www-Authenticate")) {
let auth = new_response_headers.get("Www-Authenticate");
let re = new RegExp(auth_url, 'g');
new_response_headers.set("Www-Authenticate", response_headers.get("Www-Authenticate").replace(re, workers_url));
}
if (new_response_headers.get("Location")) {
return httpHandler(e.request, new_response_headers.get("Location"))
}
let response = new Response(original_text, {
status,
headers: new_response_headers
})
return response;
}
/**
* @param {Request} req
* @param {string} pathname
*/
function httpHandler(req, pathname) {
const reqHdrRaw = req.headers
// preflight
if (req.method === 'OPTIONS' &&
reqHdrRaw.has('access-control-request-headers')
) {
return new Response(null, PREFLIGHT_INIT)
}
let rawLen = ''
const reqHdrNew = new Headers(reqHdrRaw)
const refer = reqHdrNew.get('referer')
let urlStr = pathname
const urlObj = newUrl(urlStr)
/** @type {RequestInit} */
const reqInit = {
method: req.method,
headers: reqHdrNew,
redirect: 'follow',
body: req.body
}
return proxy(urlObj, reqInit, rawLen, 0)
}
/**
*
* @param {URL} urlObj
* @param {RequestInit} reqInit
*/
async function proxy(urlObj, reqInit, rawLen) {
const res = await fetch(urlObj.href, reqInit)
const resHdrOld = res.headers
const resHdrNew = new Headers(resHdrOld)
// verify
if (rawLen) {
const newLen = resHdrOld.get('content-length') || ''
const badLen = (rawLen !== newLen)
if (badLen) {
return makeRes(res.body, 400, {
'--error': `bad len: ${newLen}, except: ${rawLen}`,
'access-control-expose-headers': '--error',
})
}
}
const status = res.status
resHdrNew.set('access-control-expose-headers', '*')
resHdrNew.set('access-control-allow-origin', '*')
resHdrNew.set('Cache-Control', 'max-age=1500')
resHdrNew.delete('content-security-policy')
resHdrNew.delete('content-security-policy-report-only')
resHdrNew.delete('clear-site-data')
return new Response(res.body, {
status,
headers: resHdrNew
})
}
部署完成后,点击设置->触发器->添加自定义域,绑定自己的域名即可。配置完成后,在 /etc/docker/daemon.json
中修改成你的域名,具体参考上方配置,然后重启 docker。
# 确认要迁移容器的名称
docker ps -a
# 打包容器为新的镜像
docker commit 容器名 镜像名
# 把镜像保存为tar文件
docker save 镜像名 >文件名称.tar
# 将文件传输到另一台服务器,用SCP命令
scp -P 22 /文件路径/文件名称.tar root@接收文件的服务器的IP:/存放文件的目录
# 恢复镜像
docker load < 文件名称.tar
恢复镜像后,用同样的方法创建容器即可。
]]>library initialization failed - unable to allocate file descriptor table - out of memorylibrary
initialization failed - unable to allocate file descriptor table - out of memory
在这里记录下解决方案。
通过重写 Docker 的 ExecStart 的参数解决
sudo systemctl edit docker
进入后,添加或者修改对应参数
[Service]
ExecStart=
ExecStart=/usr/bin/dockerd --default-ulimit nofile=65536:65536 -H fd://
最后重启 Docker
sudo systemctl daemon-reload
sudo systemctl restart docker
]]>ifconfig docker0 down
yum -y install bridge-utils
brctl delbr docker0
这样处理后,才算彻底删除了 Docker 环境。
注意:如果你没有删除删除 Docker 环境,那么下次系统启动 Docker Daemon 时还是会自动创建 docker0 网桥。
]]>docker exec -it 容器名/容器ID /bin/bash
进入容器报错报错信息如下:
OCI runtime exec failed: exec failed: container_linux.go:380: starting container process caused: exec: "/bin/bash": stat /bin/bash: no such file or directory: unknown
查看相应镜像发现镜像是使用alpine制作的
再次输入命令
docker exec -it 容器名/容器ID /bin/sh
进入成功
]]>docker kill $(docker ps -a -q)
docker rm $(docker ps -a -q)
docker rmi $(docker images -q)
systemctl stop docker
rm -rf /etc/docker
rm -rf /run/docker
rm -rf /var/lib/dockershim
rm -rf /var/lib/docker
如果发现删除不掉,需要先 umount,如
umount /var/lib/docker/devicemapper
查看已安装的 docker 包
yum list installed | grep docker
卸载相关包
yum remove docker-ce*
yum remove containerd.io.x86_64
]]>之前博客搭建在阿里云的机器上,现在快过期了,加上原机器带宽太小,就不打算续费了,现在就需要将 Typecho 博客迁移到新机器上。以前使用的是宝塔面板搭建的,现在不想把机器环境搞得乱七八糟,因此选择使用 Docker 来搭建 Typecho。
使用一键脚本安装Docker
curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun && systemctl start docker && systemctl enable docker
如果提示 curl 命令不存在,就需要先安装 curl
# Centos
yum -y install curl
# Ubuntu、Debian
apt -y install curl
如果你机器是国内的机器,那么需要配置镜像加速
阿里云镜像获取地址:https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors
修改 /etc/docker/daemon.json
,文件不存在就创建一个
{
"registry-mirrors": [
"你的加速地址"
]
}
这里选择的是 Mariadb,可自行选择数据库镜像,这里配置参数就不做解释了,懂的都懂
docker run -d -v /home/mysql:/var/lib/mysql \
-p 3306:3306 -e MYSQL_ROOT_PASSWORD=密码 \
--privileged=true --restart=always --name mariadb mariadb
安装官方的 php:7.2-fpm 镜像后,还需要进入容器安装 mysql pdo
才能使用 Mysql
数据库,比较麻烦,这里我自己在 php:7.2-fpm 的基础上构建了个带 mysql pdo
的镜像,可以选择性使用。
docker run -d -v /home/nginx/html:/var/www/html \
-p 8080:8080 --link mariadb:mariadb --name php dqjdda/php
docker run -d \
--link php:php \
--name nginx --restart always \
-p 80:80 -p 443:443 \
-e "TZ=Asia/Shanghai" \
-v /home/nginx/nginx.conf:/etc/nginx/nginx.conf \
-v /home/nginx/conf.d:/etc/nginx/conf.d \
-v /home/nginx/logs:/var/log/nginx \
-v /home/nginx/cert:/etc/nginx/cert \
-v /home/nginx/html:/var/www/html \
nginx
/home/nginx/conf.d
用于放配置文件/home/nginx/logs
存放日志/home/nginx/cert
存放证书/home/nginx/html
存放网页在 /home/nginx/conf.d
目录创建文件 blog.conf
server {
listen 443 ssl http2;
server_name izlzl.com;
gzip on;
# 缓存SSL
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
# 证书配置
ssl_certificate /etc/nginx/cert/ydyno.com/ydyno.com_chain.crt;
ssl_certificate_key /etc/nginx/cert/ydyno.com/ydyno.com_key.key;
root /var/www/html/ydyno;
index index.php;
# 伪静态
if (!-e $request_filename) {
rewrite ^(.*)$ /index.php$1 last;
}
location ~ .*\.php(\/.*)*$ {
include fastcgi_params;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info;
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_index index.php;
fastcgi_pass php:9000;
}
location ~* \.(jpg|jpeg|gif|png|css|js|ico|xml)$ {
expires 5d;
}
# deny access to . files, for security
location ~ /\. {
log_not_found off;
deny all;
}
}
server {
listen 80;
server_name izlzl.com ydyno.com;
return 301 https://izlzl.com$request_uri;
}
直接将老服务器的博客目录移动到 /var/www/html/ydyno
,然后将数据库导出,然后导入到新库即可