一直想搭建一个图床,毕竟自己的是可控的,备份很方便、数据很安全。由于不知道自己什么时候会更换vps,而且这些图床对web环境要求比较严苛,所以使用了Docker安装的图床。
docker的优点很多:
不用搭建那麻烦死人的web环境,我使用lnmp和宝塔均搭建失败。
换机时只需要打包对应的文件即可,十分钟后又是一条‘好汉’。
安装过程中会遇到的问题:
- 使用vim/vi粘贴docker-compose.yaml会出现格式错乱
解决方案:Esc + : 输入set paste
- 使用nginx反代后在图床里看到是本地IP(172.23.0.1)连接的,而在nginx的访问日志里的IP是CDN的IP ??
解决方案:
nginx日志参考我前面写的:
传送门1
Nginx获取用户真实ip
需要挂载functions.php
需要先 docker cp chevereto:/var/www/html/lib/G/functions.php /home/<username>/chevereto/lib/G/functions.php
/home//chevereto/lib/G/functions.php:/var/www/html/lib/G/functions.php:rw
在大约852行修改为 return $_SERVER['HTTP_X_FORWARDED_FOR'];
如果使用的CDN是CF的话可以改成 HTTP_CF_CONNECTING_IP
,但是如果后期不适应CF的话还需要改回原来的代码,建议改成 HTTP_REAL_IP
如果使用的不是CF就会自动把IP设置为 SERVER_ADDR
3.
1 2 3 4 5 6 7 8 9 10 11 12
| map $HTTP_CF_CONNECTING_IP $real{ "" $remote_addr; ~^(?P<firstAddr>[0-z\.]+),?.*$ $HTTP_CF_CONNECTING_IP; }
proxy_set_header REAL-IP $real;
nginx -t nginx -s reload
|
我们需要明白 REAL-IP
代表变量,HTTP_REAL_IP
代表变量的值
推荐第三种,如果使用cf那么获得的ip是HTTP_CF_CONNECTING_IP
,如果不使用cf而是直连,那么获得的ip是remote_addr
最后
1
| docker-compose down && docker-compose up -d
|
- 解决Chevereto图床上传大图片提示Internal Server error
php.ini
1 2 3 4 5
| max_execution_time = 1000 max_input_time = 1000 memory_limit = 1024M upload_max_filesize = 100M post_max_size = 100M
|
nginx.conf
1
| client_max_body_size 64M
|
1 2
| nginx -s reload docker-compose down && docker-compose up -d
|
1 2
| mkdir -p /home/<username>/chevereto/app vim /home/<username>/chevereto/app/php.ini
|
php.ini
1 2 3 4 5
| max_execution_time = 1000 max_input_time = 1000 memory_limit = 1024M upload_max_filesize = 100M post_max_size = 100M
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| version: '3' services: db: image: mariadb container_name: mariadb_chevereto volumes: - /home/<username>/chevereto/db_cheve:/var/lib/mysql:rw restart: always privileged: true networks: - private environment: MYSQL_ROOT_PASSWORD: passwd MYSQL_DATABASE: chevereto MYSQL_USER: chevereto MYSQL_PASSWORD: cheve_passwd
chevereto: depends_on: - db image: nmtan/chevereto:1.4.1 container_name: chevereto restart: always networks: - private environment: CHEVERETO_DB_HOST: db CHEVERETO_DB_USERNAME: chevereto CHEVERETO_DB_PASSWORD: cheve_passwd CHEVERETO_DB_NAME: chevereto CHEVERETO_DB_PREFIX: chv_ volumes: - /home/<username>/chevereto/images:/var/www/html/images:rw - /home/<username>/chevereto/app/php.ini:/usr/local/etc/php/php.ini:ro - /home/<username>/chevereto/lib/G/functions.php:/var/www/html/lib/G/functions.php:rw ports: - 127.0.0.1:4578:80
networks: private:
|
之前比较担心数据库的端口3306会与之前创建的数据库相冲突,查询后发现db和cheverteo在一个名为compose_private的本地网络中,其中mariadb的端口3306并没有外显出来,只是在private这个网络段里可以使用。
所以我们可以只需要关闭4578端口就行了。
只需要改成 127.0.0.1:4578:80
就行了。
我们也可以在nginx_conf中设置如果 $host
为IP格式就返回403。
1 2 3 4
| if ($host ~ "[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}") { return 403; }
|
这样使用api上传图片,用户就变成了游客,看着很不舒服
content
文件夹主要与系统和用户设置有关;而app/routes
则与相册的设置有关,我们需要把这两个文件夹从容器中映射出来。
首先进入容器中,打包这两个文件夹,然后移动到之前已经映射的images文件夹内,然后回到shell,将这两个文件夹解压并映射。
直接使用 docker cp
命令复制即可,无需下面复杂的操作
1 2 3 4 5 6 7 8 9 10 11 12
| docker exec -it chevereto /bin/bash tar czvf content.tar.gz ./content tar czvf routes.tar.gz ./app/routes/ mv content.tar.gz routes.tar.gz ./images CRTL + A + D cd /home/<username>/chevereto/images mv content.tar.gz routes.tar.gz .. tar xzvf content.tar.gz tar xzvf routes.tar.gz rm content.tar.gz routes.tar.gz
docker-compose up -d
|
然后修改route文件夹下route.api.php
1 2 3 4 5
| vim /home/<username>/chevereto/app/routes/route.api.php
$uploaded_id = CHV\Image::uploadToWebsite($source, 'test', array('album_id'=>5));
|
test为你的用户名,在右上角
album_id为你的相册ID,建议新建一个相册,然后点击详细信息。
nginx配置文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
| server { listen 80; server_name img.demo.com; if ($http_user_agent ~* "qihoobot|Baiduspider|Googlebot|Googlebot-Mobile|Googlebot-Image|Mediapartners-Google|Adsbot-Google|Feedfetcher-Google|Yahoo! Slurp|Yahoo! Slurp China|YoudaoBot|Sosospider|Sogou spider|Sogou web spider|MSNBot|ia_archiver|Tomato Bot" ) { return 403; } # 上传大图片开启 client_max_body_size 64M; # 禁止IP访问 if ($host ~ "[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}") { return 403; } location ~ .*\.(gif|jpg|jpeg|png|bmp|swf|webp)$ { proxy_pass http://127.0.0.1:4578; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header REMOTE-HOST $remote_addr; add_header X-Cache $upstream_cache_status; add_header Cache-Control max-age=864000; } location / { proxy_pass http://127.0.0.1:4578; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header REMOTE-HOST $remote_addr; add_header X-Cache $upstream_cache_status; add_header Cache-Control no-cache; } access_log /www/wwwlogs/img.demo.com.log; error_log /www/wwwlogs/img.demo.com.error.log; }
|
解释一下nginx的配置信息
server_name:表示对应的域名,如果有多个可以中间以空格隔开
每个if语句的if后面要有一个空格,例:if ($
。不要轻易使用if。
第一个location的作用:如果匹配到以 (gif|jpg|jpeg|png|bmp|swf|webp)
结尾的就不会继续向下匹配,在这个location中我们可以增加一个响应头告诉CDN或者浏览器对这个资源的缓存时间。
第二个location的作用:起到一个收底的作用,因为图床中不止有图片静态资源,所以这个里面加了一个响应头 no-cache
,可以缓存资源但是要验证资源的有效性。
如果这两个location更换位置,那么location ~ .*\.(gif|jpg|jpeg|png|bmp|swf|webp)$
,则不会起作用,因为 location /
能匹配一切。
将 add_header Cache-Control max-age=864000;
写在 location /
里面虽然不会出现问题,但是感觉很奇怪。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| version: '3.3' services: easyimage: image: 'ddsderek/easyimage:latest' container_name: 'easyimage' restart: 'unless-stopped' ports: - '127.0.0.1:4579:80' environment: - 'TZ=Asia/Shanghai' - 'PUID=1000' - 'PGID=1000' volumes: - /home/<username>/easyimage/config:/app/web/config - /home/<username>/easyimage/i:/app/web/i
|
需要先将 admin.inc.php
复制到 /home/<username>/easyimage/admin/
再取消注释的最后一行,目的是修改图床里面显示的IP地址。
1 2
| docker cp easyimage:/app/web/admin/admin.inc.php /home/<username>/easyimage/admin/admin.inc.php
|
如果在 nginx.conf 里设置 map ,那么就修改 admin/admin.inc.php 的大约第937行 $_SERVER["SERVER_ADDR"]
改为 $_SERVER["HTTP_REAL_IP"]
,如果没有添加 map 就改为 $_SERVER["HTTP_CF_CONNECTING_IP"]
。
为了安全建议设置成这样,然后将默认全部api禁用
nginx配置文件:
这个内容请参考上面那个,它们具有很大的相似性。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| server { listen 80; server_name image.demo.com; location / { proxy_pass http://127.0.0.1:4579; proxy_set_header Host $host; proxy_set_header remote_addr $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header REMOTE-HOST $remote_addr; add_header X-Cache $upstream_cache_status; add_header Cache-Control no-cache; } if ($http_user_agent ~* "qihoobot|Baiduspider|Googlebot|Googlebot-Mobile|Googlebot-Image|Mediapartners-Google|Adsbot-Google|Feedfetcher-Google|Yahoo! Slurp|Yahoo! Slurp China|YoudaoBot|Sosospider|Sogou spider|Sogou web spider|MSNBot|ia_archiver|Tomato Bot" ) { return 403; } access_log /www/wwwlogs/image.demo.com.log; #日志可以不写 error_log /www/wwwlogs/image.demo.com.error.log; }
|
1 2
| chmod -R 755 /home/usermame/easyimage/i chown -R www:www /home/usermame/easyimage
|
3.使用API上传图片
PicGo有app和cli两种方式,我觉得还是chevereto使用cli比较好用,设置简单。
最简单
可能需要node.js环境
Typora有两种上传图片的方式:
- 每粘贴或复制一张图片点击一次上传。
- 在编辑完整个文档之后,点击
格式->图像->上传所有本地图片
来一次性的将整个文档的图片都上传。
a. 对于chevereto
插件设置里面搜索chevereto
url: http://域名/api/1/upload
key: http://域名/dashboard/settings/api
b. 对于EasyImages
插件设置里面搜索web-uploader,可能需要node.js环境
1 2 3 4
| API地址: https: POST参数名: image JSON路径: url 自定义Body: {"token":"1c17b11693cb5ec63859b091c5b9c1b2"}
|
token建议删除所有默认的,然后新建一个,https://域名/admin/admin.inc.php,
cli:
先安装node.js环境
1 2
| npm install picgo -g picgo install chevereto
|
CMD打开
1 2 3
| notepad %HOMEPATH%\.picgo\config.json #或者 notepad %UserProfile%\.picgo\config.json
|
a. 对于chevereto
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| { "picBed": { "current": "chevereto", "uploader": "chevereto", "chevereto": { "key": "上面从api里面获得的密钥", "source_param": "source", "url": "https://域名/api/1/upload", "url_param": null } }, "picgoPlugins": { "picgo-plugin-chevereto": true } }
|
b. 对于EasyImage
1 2
| picgo install web-uploader picgo set uploader
|
CMD打开
1
| notepad %HOMEPATH%\.picgo\config.json
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| { "picBed": { "uploader": "web-uploader", "current": "web-uploader", "web-uploader": { "url": "https://域名/api/index.php", "paramName": "image", "jsonPath": "url", "customHeader": "", "customBody": "{\"token\":\"1c17b11693cb5ec63859b091c5b9c1b2\"}" } }, "picgoPlugins": { "picgo-plugin-web-uploader": true } }
|
- python
Docker系列五自建图床 | 君匡博客 (clzly.xyz)
这个博主写的python方案看着不错,可以试一试。
引用与参考:
nmtan/chevereto - Docker Image | Docker Hub
ddsderek/easyimage - Docker Image | Docker Hub
keven1024/chevereto-free-multi-language: multi-language chevereto ( 支持多国语言的chevereto-free ) (github.com)
rodber/chevereto-free: Self-hosted Image Hosting solution. Start your own Flickr/imgur alternative with your own rules. (github.com)
Docker系列五自建图床 | 君匡博客 (clzly.xyz)
icret/EasyImages2.0: 新版简单强大无数据库的图床2.0版 演示地址: (github.com)
简介 · 简单图床-EasyImage2.0 使用手册 · 看云 (kancloud.cn)
修改Chevereto的API上传相册和用户_飞逝17的博客-CSDN博客
get_real_ip-github
php中$_SERVER参数HTTP_X_FORWARDED_FOR & REMOTE_ADDR与获取IP
Cache-Control MDN