"시놀로지 도커 설정"의 두 판 사이의 차이
둘러보기로 이동
검색으로 이동
Kim135797531 (토론 | 기여) (새 문서: ===== Nginx 프록시 서버 ===== * 이건 도커가 아닌 시놀로지 VMM에 위치 * Alpine * Cloudflare 연동 expose 서버 * 일본 특성상 IPv4 포트가 매우 제한적...) |
Kim135797531 (토론 | 기여) 잔글 (→Deluge (토렌트) (도커)) |
||
(같은 사용자의 중간 판 20개는 보이지 않습니다) | |||
1번째 줄: | 1번째 줄: | ||
===== | == 외부 노출 서버 (시놀로지 VMM) == | ||
* alpine-virt-3.11.3 | |||
=== 역할 === | |||
* 현재 IPv6 Cloudflare에 보고(갱신) | |||
* 웹 프록시 | |||
=== 마운트 설정 === | |||
* alpine에 nfsmount 설치 | |||
** apk add nfsmount | |||
* /etc/fstab에 다음 내용 추가 | |||
** 맨 뒤의 _netdev와 0 0을 꼭 추가해야 한다 (안하면 네트워크 연결 전에 마운트 시도해서 부팅 안 됨)<syntaxhighlight lang="sh"> | |||
내부서버IP:/volume1/시놀로지폴더 /마운트경로 nfs nfsvers=3,rsize=524288,wsize=524288,ro,auto,nolock,_netdev 0 0 | |||
</syntaxhighlight> | |||
=== Cloudflare 연동 IP 등록 === | |||
* 일본 특성상 IPv4 포트가 매우 제한적으로 열려 있고, 10000번대 밑으로는 아예 열리지도 않음 | * 일본 특성상 IPv4 포트가 매우 제한적으로 열려 있고, 10000번대 밑으로는 아예 열리지도 않음 | ||
* IPv6는 이런 제한이 없음. 공유기가 각각의 머신에 뿌려주는 IP는 DHCP라기보다는 일본 인터넷에 직접 연결된 공인 IP. | * IPv6는 이런 제한이 없음. 공유기가 각각의 머신에 뿌려주는 IP는 DHCP라기보다는 일본 인터넷에 직접 연결된 공인 IP. | ||
** IPv6는 설계시부터 모든 기기가 고유의 공인 IP를 갖는 형태로 설계됨. 다만 그 특성상 보안에 취약하므로, 영구 IPv6 주소와 별개로 임시 IPv6가 부여되어, 수시로 주소가 바뀜. | ** IPv6는 설계시부터 모든 기기가 고유의 공인 IP를 갖는 형태로 설계됨. 다만 그 특성상 보안에 취약하므로, 영구 IPv6 주소와 별개로 임시 IPv6가 부여되어, 수시로 주소가 바뀜. | ||
** 주소 바뀜을 체크하여, Cloudflare DNS에 등록해 주는 역할 | ** 주소 바뀜을 체크하여, Cloudflare DNS에 등록해 주는 역할 (v6 레코드인 AAAA를 업데이트 함) | ||
** 다음 파일을 alpine 서버의 /etc/init.d에 | ** 다음 파일을 alpine 서버의 /etc/init.d에 저장. (파일 이름 cloudflare-alpine.service)<syntaxhighlight lang="shell" line="1"> | ||
#!/sbin/openrc-run | #!/sbin/openrc-run | ||
22번째 줄: | 36번째 줄: | ||
description="Update Cloudflare DNS" | description="Update Cloudflare DNS" | ||
command="/usr/bin/python3 /root/cloudflare-alpine.py" | |||
pidfile="/var/run/cloudflare/cloudflare.pid" | pidfile="/var/run/cloudflare/cloudflare.pid" | ||
command_background="yes" | command_background="yes" | ||
38번째 줄: | 51번째 줄: | ||
mkdir -p /var/run/cloudflare || return 1 | mkdir -p /var/run/cloudflare || return 1 | ||
} | } | ||
</syntaxhighlight>실제 업데이트를 수행하는 Python 파일을 위의 서비스 스크립트에 지정된 위치로 잘 저장<syntaxhighlight lang="python3" line="1"> | |||
#!/usr/bin/env python | |||
# -*- coding: utf-8 -*- | |||
import os | |||
import requests | |||
import json | |||
from time import sleep | |||
CLOUDFLARE_KEY = 'XXX' | |||
CLOUDFLARE_ZONE_ID = 'XXX' | |||
CLOUDFLARE_DNS_TOKEN = 'XXX' | |||
CLOUDFLARE_HEADER = { | |||
'Authorization': 'Bearer {}'.format(CLOUDFLARE_DNS_TOKEN), | |||
'Content-Type': 'application/json' | |||
} | |||
DNS_GET_URL = 'https://api.cloudflare.com/client/v4/zones/{}/dns_records'.format(CLOUDFLARE_ZONE_ID) | |||
device = 'eth0' | |||
addr_file = '/tmp/cloudflare.addr6' | |||
def check(): | |||
addr = '' | |||
try: | |||
with open(addr_file, 'r') as f: | |||
addr = f.read() | |||
except: | |||
pass | |||
get_addr_cmd = "ip -6 addr list scope global $device | " \ | |||
"grep -v ' fd' | " \ | |||
"grep -v 'deprecated' | " \ | |||
"grep -v 'mngtmpaddr' | " \ | |||
"head -n 2 | " \ | |||
"tail -n 1" | |||
new_addr = os.popen(get_addr_cmd).read() | |||
new_addr = new_addr.split()[1] | |||
new_addr = new_addr.split('/')[0] | |||
if addr == new_addr: | |||
print('same ip {}'.format(new_addr)) | |||
else: | |||
r = requests.get(DNS_GET_URL, headers=CLOUDFLARE_HEADER) | |||
j = json.loads(r.text) | |||
for item in j['result']: | |||
dns_put_url = DNS_GET_URL + '/' + item['id'] | |||
new_data = dict( | |||
type=item['type'], | |||
name=item['name'], | |||
content=new_addr, | |||
) | |||
if item['type'] == 'AAAA': | |||
new_data['proxied'] = True | |||
requests.put(dns_put_url, data=json.dumps(new_data), headers=CLOUDFLARE_HEADER) | |||
elif item['type'] == 'TXT': | |||
new_data['content'] = 'v=spf1 {} ~all'.format(new_addr) | |||
requests.put(dns_put_url, data=json.dumps(new_data), headers=CLOUDFLARE_HEADER) | |||
with open(addr_file, 'w') as f: | |||
f.write(new_addr) | |||
f.close() | |||
print('updated ip {}'.format(new_addr)) | |||
while True: | |||
check() | |||
sleep(60) | |||
</syntaxhighlight> | |||
** 그 후 서비스 등록<syntaxhighlight lang="sh"> | |||
rc-update add cloudflare-alpine.service | |||
rc-service cloudflare-alpine.service restart | |||
rc-update -u | |||
</syntaxhighlight> | |||
=== Nginx 웹 프록시 === | |||
* Cloudflare로부터 오는 HTTPS 요청을 처리하여, 내부 서버에 전달 | |||
* 처음 도입 목적은 Cloudflare의 IPv6 over IPv4 기능을 이용하기 위함 | |||
* 생각해보니 외부/내부를 분리하여 보안성도 높아지고, 도커를 이용한 로드밸런서 구현 및 포트 번호 추상화가 가능해져 채택 | |||
* /etc/nginx/conf.d는 시놀로지에 config를 등록해 놓고 폴더째로 마운트 | |||
* wiki-proxy.conf 예시 | |||
** proxy_set_header를 설정해야 내부 서버에서 보이는 접속 요청 IP가 실제 사용자의 IP로 제대로 뜬다 | |||
** 내부 서버사이의 통신은 http로 하여 속도 향상 (방화벽 설정은 따로) | |||
** TODO: upstream 요청 처리가 60초 이상 걸려도 취소 안 하게 설정하기? wiki의 restbase나 mathoid가 고장나는 이유가 이것 때문인 듯<syntaxhighlight lang="nginx"> | |||
server { | |||
listen 80; | |||
listen [::]:80; | |||
server_name wiki.dong-min.kim; | |||
location / { | |||
return 301 https://$server_name$request_uri; | |||
} | |||
} | |||
server { | |||
listen 443 ssl; | |||
listen [::]:443 ssl; | |||
ssl_certificate pem파일; | |||
ssl_certificate_key key파일; | |||
server_name wiki.dong-min.kim; | |||
server_tokens off; | |||
location / { | |||
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 X-Forwarded-Host $server_name; | |||
proxy_set_header Client-IP $remote_addr; | |||
proxy_pass http://내부 서버 주소:포트; | |||
} | |||
} | |||
</syntaxhighlight> | |||
* | |||
* | |||
* | |||
* | |||
== 웹 데몬 == | |||
=== Nginx (도커) === | |||
==== 역할 ==== | |||
* HTTP 요청을 받아서 | |||
** 직접 처리(static)하거나 | |||
** PHP 인터프리터로 보내거나 | |||
** 다른 웹 데몬(Node.js, Python, ...)으로 다시 proxy한다 | |||
==== 레포지토리 ==== | |||
* https://hub.docker.com/_/nginx | |||
* 1.17.8-alpine | |||
==== 컨테이너 설정 ==== | |||
* 포트 설정 | |||
** (외부 노출 서버 Nginx Proxy 포트 설정):(그대로) | |||
* 볼륨 설정 | |||
** htpasswd -> (비공개)/htpasswd | |||
** passwd -> /etc/passwd | |||
** www -> (비공개)/www/ | |||
** nginx/conf.d/ -> /etc/nginx/conf.d/ | |||
** nginx/nginx.conf -> /etc/nginx/nginx.conf | |||
* 환경 변수 | |||
** (기본값) | |||
== 인터프리터 == | |||
=== PHP (도커) === | |||
==== 역할 ==== | |||
* PHP 데몬 | |||
* FPM(FastCGI Process Manager) 사용하여 동적 워커 생성 | |||
==== 레포지토리 ==== | |||
* 공식 레포지토리의 7.3.31-fpm-alpine3.14 기반 | |||
* 추가로 PHP 확장 기능을 설치하기 위해 Dockerfile 작성 | |||
** gd, mysqli, intl, @composer | |||
* 이용한 라이브러리 | |||
** https://github.com/mlocati/docker-php-extension-installer | |||
* Dockerfile | |||
** https://git.dong-min.kim/kim135797531/php-fpm-kdm-extensions | |||
* 도커 레포지토리 | |||
** https://hub.docker.com/r/kim135797531/php-fpm-kdm-extensions | |||
==== 컨테이너 설정 ==== | |||
* 포트 설정 | |||
** (비공개):9000 | |||
** 참고로 www.conf에서 다른 포트로 설정해도 php-fpm.d/zz-docker.conf에서 무조건 기본값으로 바꿈 | |||
* 볼륨 설정 | |||
** php.ini -> /usr/local/etc/php/php.ini | |||
** www.conf -> /usr/local/etc/php-fpm.d/www.conf | |||
** www.conf -> /usr/local/etc/php-fpm.d/www.conf.default | |||
** www -> (비공개)/www/ | |||
**php-패스wd -> /이티시/패스wd | |||
* 환경 변수 | |||
** (기본값) | |||
==== php.ini 설정 ==== | |||
* max_execution_time = 30 | |||
* max_input_time = 60 | |||
* memory_limit = 512M | |||
* post_max_size = 10240M | |||
* upload_max_filesize = 10240M | |||
* default_socket_timeout = 30 | |||
* extension gd2, mysqli 활성화 | |||
==== www.conf 설정 ==== | |||
* 여기 설정은 주로 미디어위키의 VisualEditor 확장 기능 + Math 수식 입력기를 사용할 때 Restbase 서버에 동시에 많은 요청을 보내는 것을 처리하기 위해 필요함 | |||
* pm.max_children = 16 | |||
* pm.start_servers = 16 | |||
* pm.min_spare_servers = 16 | |||
* pm.max_spare_servers = 16 | |||
* pm.process_idle_timeout = 30s | |||
== 데이터베이스 == | |||
=== MySQL (도커) === | |||
==== 역할 ==== | |||
* 워드프레스, 미디어위키에 사용하기 위한 범용 데이터베이스 | |||
==== 레포지토리 ==== | |||
* https://hub.docker.com/_/mysql | |||
* 5.7.29 | |||
==== 컨테이너 설정 ==== | |||
* 포트 설정 | |||
** (외부 노출 서버 Nginx Proxy 포트 설정 시작 번호-2):(그대로) | |||
* 볼륨 설정 | |||
** MySQL 실제 DB 파일 폴더 -> /var/lib/mysql/ | |||
** mysql.cnf -> /etc/mysql/conf.d/mysql.cnf | |||
* 환경 변수 | |||
** (기본값) | |||
=== Cassandra (도커) === | |||
==== 역할 ==== | |||
* 미디어위키의 API 백엔드 Restbase에서 사용하기 위한 고성능 데이터베이스 | |||
==== 레포지토리 ==== | |||
* https://hub.docker.com/_/cassandra/ | |||
* 3.11.6 | |||
==== 컨테이너 설정 ==== | |||
* 포트 설정 | |||
** (비공개):9042 | |||
* 볼륨 설정 | |||
** Cassandra 실제 DB 파일 폴더 -> /var/lib/cassandra/ | |||
** Cassandra 설정 폴더 -> /etc/cassandra/ | |||
* 환경 변수 | |||
** CASSANDRA_BROADCAST_ADDRESS = (호스트 주소 - 집 안의 NAS IP) | |||
==== cassandra-env.sh 설정 ==== | |||
* https://www.mediawiki.org/wiki/Parsoid/Setup/RESTBase 참고 | |||
* MAX_HEAP_SIZE="128M" | |||
* HEAP_NEWSIZE="20M" | |||
==== cassandra.yaml 설정 ==== | |||
* https://www.mediawiki.org/wiki/Parsoid/Setup/RESTBase 참고 | |||
* key_cache_size_in_mb: 0 | |||
* concurrent_reads: 2 | |||
* concurrent_writes: 2 | |||
* rpc_server_type: hsha | |||
* rpc_min_threads: 1 | |||
* rpc_max_threads: 1 | |||
* concurrent_compactors: 1 | |||
* compaction_throughput_mb_per_sec: 0 | |||
== 응용 프로그램(애플리케이션) - Nginx 종속 == | |||
=== 워드프레스 (파일) === | |||
==== 역할 ==== | |||
* 개인 포트폴리오 | |||
* https://dong-min.kim | |||
==== wp-컨피그.php ==== | |||
* FTPS 설정 (SFTP가 아니다) | |||
* 프록시된 요청을 처리하기 위한 추가 설정 | |||
** $_SERVER['HTTPS']='on'; 구절만 있으면 된다 | |||
** 나머지는 프록시 서버 측의 설정이 잘못된 상태일 때 필요했었다 | |||
* <syntaxhighlight lang="php"> | |||
define('FTP_HOST', '내부 서버 주소:내부 포트 번호'); | |||
define('FTP_USER', 'wp-ftps'); | |||
define('FTP_PASS', ''); | |||
define('FTP_SSL', true); | |||
define('FTP_BASE', '(비공개)/wordpress/'); | |||
define('FTP_CONTENT_DIR', '(비공개)/wp-content/'); | |||
define('FTP_PLUGIN_DIR ', '(비공개)/wp-content/plugins/'); | |||
if ($_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https') | |||
$_SERVER['HTTPS']='on'; | |||
// define('RELOCATE', true); | |||
// define('WP_HOME', 'https://dong-min.kim'); | |||
// define('WP_SITEURL', 'https://dong-min.kim'); | |||
/* | |||
if ( ! empty( $_SERVER['HTTP_X_FORWARDED_HOST'] ) ) { | |||
$_SERVER['HTTP_HOST'] = $_SERVER['HTTP_X_FORWARDED_HOST']; | |||
} | |||
*/ | |||
</syntaxhighlight> | |||
=== 미디어위키 (파일) === | |||
==== 역할 ==== | |||
* 개인 위키 | |||
* https://wiki.dong-min.kim | |||
==== 확장 기능 ==== | |||
* VisualEditor, Math, SyntaxHighlight | |||
** VisualEditor와 Math를 연동할 때, 수식 편집기에서 동적 업데이트 횟수에 비례해서 서버가 느려지는 현상 발생 | |||
** Math 확장 기능에서 제공하는 MWLatexNode.js가 수식이 업데이트 될 때마다 과거 기록을 지우지 않고 전부 갖고 있는 버그가 원인 | |||
** 그 기록들도 매 번 의미없는 업데이트를 하느라 서버가 느려짐 | |||
** 임시 해결 방법 | |||
*** Math 확장 기능의 modules/ve-math/ve.ce.MWLatexNode.js 파일의 맨 아래 쪽에 다음 항목을 추가하여, 강제 업데이트를 방지 | |||
*** 이거 해도 새로 고침은 하지만, 적어도 Mathoid 서버에 새로 요청 하지는 않는다 (캐시 사용) | |||
*** <syntaxhighlight lang="javascript"> | |||
/** | |||
* @inheritdoc ve.ce.GeneratedContentNode | |||
*/ | |||
ve.ce.MWLatexNode.prototype.onGeneratedContentNodeUpdate = function ( staged ) { | |||
// 꼼수... this.root가 있을 때만 업데이트함 | |||
// this.root가 있는 노드는 실제 글 속의 math 노드 (다이얼로그 속은 root 없음) | |||
if (this.root) | |||
this.update( undefined, staged ); | |||
}; | |||
</syntaxhighlight> | </syntaxhighlight> | ||
===== Nginx config ===== | |||
* php | <syntaxhighlight lang="nginx"> | ||
* | server { | ||
** | listen ?????; | ||
** restbase | listen [::]:?????; | ||
** parsoid | server_name wiki.dong-min.kim; | ||
** mathoid | |||
** | access_log /var/log/nginx/wiki.access.log main; | ||
* 토렌트 | error_log /var/log/nginx/wiki.error.log; | ||
** | |||
* | charset utf-8; | ||
* gitlab | root ?????; | ||
** gitlab | index index.html index.htm index.php; | ||
** | |||
* | client_max_body_size 10240M; | ||
** | |||
** | # Avoid 504 HTTP Timeout Errors | ||
* | proxy_connect_timeout 605; | ||
* kb_apart | proxy_send_timeout 605; | ||
proxy_read_timeout 605; | |||
send_timeout 605; | |||
keepalive_timeout 605; | |||
fastcgi_read_timeout 605; | |||
location ~ ^/w/(index|load|thumb|opensearch_desc|api|rest|img_auth)\.php$ { | |||
include fastcgi.conf; | |||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; | |||
fastcgi_pass ?????:?????; | |||
} | |||
# Images | |||
location /w/images { | |||
# Separate location for images/ so .php execution won't apply | |||
try_files $uri 404; | |||
} | |||
location /w/images/deleted { | |||
# Deny access to deleted images folder | |||
deny all; | |||
} | |||
# MediaWiki assets (usually images) | |||
location ~ ^/w/resources/(assets|lib|src) { | |||
try_files $uri 404; | |||
add_header Cache-Control "public"; | |||
expires 7d; | |||
} | |||
# Assets, scripts and styles from skins and extensions | |||
location ~ ^/w/(skins|extensions)/.+\.(css|js|gif|jpg|jpeg|png|svg)$ { | |||
try_files $uri 404; | |||
add_header Cache-Control "public"; | |||
expires 7d; | |||
} | |||
# License and credits files | |||
location ~ ^/w/(COPYING|CREDITS)$ { | |||
default_type text/plain; | |||
} | |||
## Uncomment the following code if you wish to use the installer/updater | |||
## installer/updater | |||
# location /w/mw-config/ { | |||
# # Do this inside of a location so it can be negated | |||
# location ~ \.php$ { | |||
# include fastcgi.conf; | |||
# fastcgi_param SCRIPT_FILENAME $document_root/w/mw-config/$fastcgi_script_name; | |||
# fastcgi_pass ?????:????; # or whatever port your PHP-FPM listens on | |||
# } | |||
# } | |||
# Handling for Mediawiki REST API, see [[mw:API:REST_API]] | |||
location /w/rest.php/ { | |||
try_files $uri $uri/ /w/rest.php?$query_string; | |||
} | |||
# Handling for the article path (pretty URLs) | |||
location /view/ { | |||
rewrite ^/view/(?<pagename>.*)$ /w/index.php; | |||
} | |||
# Allow robots.txt in case you have one | |||
location = /robots.txt { | |||
} | |||
location = /favicon.ico { | |||
} | |||
location / { | |||
rewrite ^/(.*)$ /view/$1 redirect; | |||
} | |||
} | |||
</syntaxhighlight> | |||
=== LocalSettings.php === | |||
<syntaxhighlight lang="php"> | |||
<?php | |||
// ... (생략) | |||
$wgArticlePath = "/view/$1"; | |||
$wgUsePathInfo = true; | |||
$wgScriptExtension = ".php"; | |||
$wgMathValidModes[] = 'mathml'; | |||
$wgDefaultUserOptions['math'] = 'mathml'; | |||
$wgMathFullRestbaseURL = 'https://wiki-restbase.dong-min.kim/wiki.dong-min.kim/'; | |||
$wgMathMathMLUrl = 'https://wiki-mathoid.dong-min.kim'; | |||
# START VisualEditor Setting | |||
$wgGroupPermissions['user']['writeapi'] = true; | |||
wfLoadExtension( 'Parsoid', 'vendor/wikimedia/parsoid/extension.json' ); | |||
# END VisualEditor Setting | |||
?> | |||
</syntaxhighlight> | |||
=== 미디어위키 Restbase (도커) === | |||
* 이 Restbase를 비롯하여 아래의 Parsoid, Mathoid는 미디어위키에서 Visual Editor + Math 확장 기능을 사용하기 위해 설치함 | |||
* 원래 미디어위키에서 무료로 제공하는 기본 Restbase서버와 Mathoid 서버를 이용해도 되지만, 속도가 정말 '''<big>끔찍</big>하게''' 느려서 직접 구축 | |||
* 제대로 된 문서가 없어서 구축 삽질 엄청 했다... 코드 안에 mediawiki url 하드코딩이 너무 많아 뭐가 문제인지 발견하기가 힘들었다 | |||
==== 역할 ==== | |||
* 미디어위키의 API를 처리하기 위한 REST 처리 서버 | |||
* REST로 받은 요청을 내부 독립 서버 (Parsoid, Mathoid 등)에 전달 및 반환 결과 캐싱 | |||
* 기본 DB 세팅인 SQLite는 동시에 많은 요청이 들어오면 db파일이 죽는 경우가 있어서, Cassandra 세팅으로 바꿈 | |||
* Node.js | |||
==== 레포지토리 ==== | |||
* 인터넷에 떠도는 Dockerfile 기반으로 몇 가지 하드코딩을 넣어 이미지 생성 | |||
* Dockerfile | |||
** https://git.dong-min.kim/kim135797531/docker-restbase | |||
* Restbase 소스 (하드코딩 + 버그 수정) | |||
** https://git.dong-min.kim/kim135797531/docker-restbase-src | |||
* 도커 레포지토리 | |||
** https://hub.docker.com/repository/docker/kim135797531/docker-restbase | |||
==== 컨테이너 설정 ==== | |||
* 포트 설정 | |||
** (비공개):7231 | |||
* 볼륨 설정 | |||
** config.yaml -> /mount/config.yaml | |||
* 환경 변수 | |||
** (기본값) | |||
=== 미디어위키 Parsoid (도커) === | |||
==== 역할 ==== | |||
* 미디어위키의 Visual Editor 등에서 html <-> wikitext 간 변환 등을 위해 문서 실시간 파싱 등을 처리 | |||
* Node.js | |||
==== 레포지토리 ==== | |||
* 인터넷에 떠도는 Dockerfile 기반으로 몇 가지 하드코딩을 넣어 이미지 생성 | |||
* Dockerfile | |||
** https://git.dong-min.kim/kim135797531/docker-parsoid | |||
* Restbase 소스 (하드코딩 + 버그 수정) | |||
** https://git.dong-min.kim/kim135797531/docker-parsoid-src | |||
* 도커 레포지토리 | |||
** https://hub.docker.com/repository/docker/kim135797531/docker-parsoid | |||
==== 컨테이너 설정 ==== | |||
* 포트 설정 | |||
** (비공개):8000 | |||
** (비공개):8001 | |||
* 볼륨 설정 | |||
** config.yaml -> /mount/config.yaml | |||
* 환경 변수 | |||
** (기본값) | |||
=== 미디어위키 Mathoid (도커) === | |||
==== 역할 ==== | |||
* 미디어위키의 Math 확장 기능에서 사용 | |||
* LaTeX 문법을 svg, png 등으로 변환 | |||
* Node.js 10 | |||
* pm2로 서비스화 시킴 | |||
==== 레포지토리 ==== | |||
* 인터넷에 떠도는 Dockerfile 기반으로 몇 가지 하드코딩을 넣어 이미지 생성 | |||
* Dockerfile | |||
** https://git.dong-min.kim/kim135797531/docker-mathoid | |||
* Restbase 소스 (하드코딩 + 버그 수정) | |||
** https://git.dong-min.kim/kim135797531/docker-mathoid-src | |||
* 도커 레포지토리 | |||
** https://hub.docker.com/repository/docker/kim135797531/docker-mathoid | |||
==== 컨테이너 설정 ==== | |||
* 포트 설정 | |||
** (비공개):10042 | |||
* 볼륨 설정 | |||
** config.yaml -> /mount/config.yaml | |||
* 환경 변수 | |||
** (기본값) | |||
=== Deluge (토렌트) (도커) === | |||
==== 역할 ==== | |||
* 토렌트 서버 | |||
* 컨테이너를 완전히 OpenVPN으로 감싸서, VPN 등록이 되지 않은 상태에서는 네트워크 접속을 원천 차단 | |||
* *.ovpn 파일은 config 폴더에 넣으면 됨 | |||
* vpn 서버의 IP 주소를 찾지 못하므로, /etc/hosts에 수동으로 IP주소 써 주기 | |||
* (일본 한정) v6플러스의 포트 포화를 막기 위해, 토렌트 속도를 희생하고 timeout이 없는 UDP가 아닌 timeout도 있고 공유기가 IP 마스커레이드도 잘 해주는 TCP로 vpn 설정 | |||
==== 레포지토리 ==== | |||
* https://hub.docker.com/r/binhex/arch-delugevpn | |||
==== 컨테이너 설정 ==== | |||
* 포트 설정 | |||
** (기본값) | |||
* 볼륨 설정 | |||
** config/ -> /config | |||
** (자료 저장 폴더) -> /data | |||
* 환경 변수 | |||
** NAME_SERVERS = 1.1.1.1 | |||
** LAN_NETWORK = 호스트의 아이피 말고 호스트의 서브넷 (xxx.xxx.xxx.xxx/xx) | |||
** ENABLE_PRIVOXY = yes | |||
** PGID = 100 | |||
** PUID = 1026 | |||
** VPN_PROV = custom | |||
** VPN_ENABLED = yes | |||
** HOME = /config/home | |||
=== Gitlab === | |||
==== 역할 ==== | |||
* 사설 Git 서버 | |||
==== 레포지토리 ==== | |||
* https://hub.docker.com/r/gitlab/gitlab-ce/ | |||
* 12.8.8 | |||
==== 컨테이너 설정 ==== | |||
* 포트 설정 | |||
** (비공개):22 | |||
** (비공개):80 | |||
** (비공개):443 | |||
** (비공개):5005 | |||
* 볼륨 설정 | |||
** gitlab 실제 자료 폴더 -> /var/opt/gitlab/ | |||
** gitlab 설정 폴더 -> /etc/gitlab/ | |||
==== gitlab.rb 설정 ==== | |||
* external_url 'https://git.dong-min.kim<nowiki/>' | |||
* gitlab_rails['gitlab_ssh_host'] = 'kasumi.synology.me' | |||
* gitlab_rails['time_zone'] = 'Asia/Seoul' | |||
* gitlab_rails['gitlab_default_theme'] = 10 # dark(default) = 2, red = 9, light red = 10 | |||
* gitlab_rails['trusted_proxies'] = ['시놀로지IP', '프록시IP'] | |||
* gitlab_rails['gitlab_shell_ssh_port'] = 64100 | |||
* registry_external_url 'https://registry.dong-min.kim<nowiki/>' | |||
* gitlab_rails['registry_enabled'] = true | |||
* unicorn['worker_processes'] = 2 | |||
* sidekiq['concurrency'] = 3 # default 25 | |||
* nginx['gzip_enabled'] = false | |||
* nginx['listen_port'] = 80 | |||
* nginx['listen_https'] = false | |||
* registry_nginx['enable'] = true | |||
* registry_nginx['gzip_enabled'] = false | |||
* registry_nginx['listen_port'] = 5005 | |||
* registry_nginx['listen_https'] = false | |||
==== 업데이트 ==== | |||
* 업그레이드 패스 참조: https://gitlab-com.gitlab.io/support/toolbox/upgrade-path/ | |||
* 컨테이너 들어가기 | |||
* 서비스 중지 | |||
** gitlab-ctl stop | |||
* 컨테이너 정지 | |||
* 컨테이너 삭제 | |||
* 새 컨테이너 생성 | |||
** (비공개):80 | |||
** (비공개):443 | |||
** (비공개):22 | |||
** (비공개):5005 | |||
** gitlab 실제 자료 폴더 -> /var/opt/gitlab/ | |||
** gitlab 설정 폴더 -> /etc/gitlab/ | |||
* 상태 확인: https://git.dong-min.kim/admin/background_migrations | |||
* 최종 확인 | |||
** gitlab-rake gitlab:check | |||
=== Gitlab Runner === | |||
==== 역할 ==== | |||
* Gitlab의 CI/CD 실행용 Runner | |||
==== 레포지토리 ==== | |||
* https://hub.docker.com/r/gitlab/gitlab-runner/ | |||
* 12.8.0 | |||
==== 컨테이너 설정 ==== | |||
* 파일 설정 | |||
** docker.sock -> /var/run/docker.sock | |||
* 볼륨 설정 | |||
** gitlab runner 설정 폴더 -> /etc/gitlab-runner | |||
* 주의점 | |||
** 시놀로지 docker를 쓰려면 시놀로지의 docker.sock이 필요하다. | |||
*** 먼저 시놀로지 측에서 sudo ln -s /var/run/docker.sock /volume1/docker/docker.sock 으로 심볼릭 링크 생성 | |||
*** Gitlab Runner 컨테이너 생성할 때 위 파일 링크가 안 됨 | |||
*** 먼저 아무 파일이나 링크해서 일단 컨테이너 생성 | |||
*** 컨테이너 설정 백업해서, 그 파일 안에서 링크 수정 | |||
*** 수정한 컨테이너 설정을 다시 로드 | |||
** 컨테이너 실행 후 gitlab-runner register 명령어로 gitlab 등록 | |||
=== kb_apart (광규 외주) (도커) === | |||
==== 역할 ==== | |||
* 광규 외주 프로그램 - 아파트 시세 확인 | |||
* gliderlabs/alpine:3.3 기반 (glibc 설치용) | |||
* Miniconda3 설치 | |||
* Python 3.7.5 + Flask | |||
==== 레포지토리 ==== | |||
* Dockerfile | |||
** https://git.dong-min.kim/kim135797531/docker-kb-apart-src | |||
* 도커 레포지토리 없음 (비공개 코드) | |||
** tar 파일로 직접 업로드 | |||
==== 컨테이너 설정 ==== | |||
* 포트 설정 | |||
** (비공개):5000 | |||
* 볼륨 설정 | |||
** 법정동.txt -> /var/lib/kb_apart/utils/법정동.txt | |||
* 환경 변수 | |||
** CONDA_ENV_NAME = kb_apart | |||
=== Internet Speed Logger (도커) === | |||
==== 역할 ==== | |||
* 일정 주기마다 Speedtest 사이트로 속도 측정해서 그래프로 표시 | |||
* 자꾸 집 인터넷 QoS 걸리는 것 같아서 설치함 | |||
==== 레포지토리 ==== | |||
* 도커 레포지토리 | |||
** https://hub.docker.com/r/vkentta/internet-speed-logger | |||
==== 컨테이너 설정 ==== | |||
* 포트 설정 | |||
** (비공개):3000 | |||
* 볼륨 설정 | |||
** internet speed logger 설정 폴더 -> /usr/src/app/data | |||
* 환경 변수 | |||
** CHECK_PERIOD_MINUTES = 30 | |||
** | |||
== 응용 프로그램(애플리케이션) - 독립형 == | |||
=== busybox (도커) === | |||
==== 역할 ==== | |||
* 도커 게스트 관점에서 바라보는 파일 권한 확인, 간단한 명령어 (curl이나 ping 등) 실행용 | |||
==== 레포지토리 ==== | |||
* https://hub.docker.com/_/busybox | |||
* 1.31.1-glibc | |||
==== 컨테이너 설정 ==== | |||
* 포트 설정 | |||
** (없음) | |||
* 볼륨 설정 | |||
** www -> (비공개)/www/ | |||
* 환경 변수 | |||
** (기본값) | |||
=== openvpn (도커) === | |||
==== 역할 ==== | |||
* OpenVPN Client 를 수행해서, 그 결과를 SOCKS5 프록시 서버로 통신 가능 | |||
* OpenVPN to SOCKS5/HTTP Proxy Docker Image | |||
* 시놀로지 도커에서 자꾸 IPV6 설정 실패하니, ovpn 파일 안의 | |||
** ovpn 파일 안에 proto udp를 proto udp4로 | |||
** setenv UV_IPV6 yes 주석처리 | |||
==== 레포지토리 ==== | |||
* https://registry.hub.docker.com/r/curve25519xsalsa20poly1305/openvpn/ | |||
* latest | |||
==== 컨테이너 설정 ==== | |||
* 포트 설정 | |||
** (비공개):1080 tcp | |||
** (비공개):1080 udp | |||
* 볼륨 설정 | |||
** (openvpn 설정폴더)/vpn -> /vpn | |||
** /dev/net/tun -> /dev/net/tun (필요없을수도?) | |||
* 환경 변수 | |||
** OPENVPN_CONFIG = /vpn/설정파일.ovpn | |||
== 권한 관련 팁 == | |||
Nginx, PHP의 404 Not found 오류는 권한 문제일 때가 많다. 도커에서 실행중이라고 했을 때 살펴볼 것은 | |||
* 컨테이너 내에서 Nginx나 PHP를 실행하고 있는 uid는 무엇인가? | |||
** 해당 uid가 파일을 읽을 수 있는가? 쓸 수 있는가? | |||
* uid가 속해 있는 그룹 확인 (gid) | |||
** 해당 gid가 파일을 읽을 수 있는가? 쓸 수 있는가? | |||
* 권한이 있는데도 접근이 안 되는 경우 | |||
** 루트 디렉터리에서부터 시작해서, 해당 파일이 있는 디렉터리까지의 경로까지 중에서 현재 uid 또는 gid로 '''실행 권한'''을 얻을 수 있는지 확인할 것. | |||
** 읽기, 쓰기 권한이 아니라 실행 권한이다. | |||
* 겉으로 보기에는 같은 www-data이더라도 컨테이너에 따라 id는 다를 수 있다. | |||
* 시놀로지의 경우 NFS 서버로 마운트한 클라이언트에서 본 권한과도 다를 수 있기 때문에 주의 | |||
* LDAP 설정해서 동기화 하려 했으나 귀찮아서 일단 보류 | |||
== 집 Docker Swarm 삽질 == | |||
=== GUI 프로그램 === | |||
==== Portainer (9000) ==== | |||
* 가능 | |||
** gitlab 연동 가능 | |||
** gitlab 레지스트리에서 이미지 push/pull 가능 | |||
** '''터미널 실행 가능''' | |||
* 불가 | |||
** gitlab 레지스트리 목록 보기 불가 | |||
** 이미지에서 마우스로 컨테이너 실행 불가 | |||
==== Swarmpit (888) ==== | |||
* 가능 | |||
** gitlab 연동 가능 | |||
** gitlab 레지스트리에서 이미지 push/pull 가능 | |||
** gitlab 레지스트리 목록 보기 가능 | |||
** '''이미지에서 마우스로 컨테이너 실행 가능''' | |||
* 불가 | |||
** 터미널 실행 불가 |
2024년 8월 12일 (월) 06:11 기준 최신판
외부 노출 서버 (시놀로지 VMM)
- alpine-virt-3.11.3
역할
- 현재 IPv6 Cloudflare에 보고(갱신)
- 웹 프록시
마운트 설정
- alpine에 nfsmount 설치
- apk add nfsmount
- /etc/fstab에 다음 내용 추가
- 맨 뒤의 _netdev와 0 0을 꼭 추가해야 한다 (안하면 네트워크 연결 전에 마운트 시도해서 부팅 안 됨)
내부서버IP:/volume1/시놀로지폴더 /마운트경로 nfs nfsvers=3,rsize=524288,wsize=524288,ro,auto,nolock,_netdev 0 0
- 맨 뒤의 _netdev와 0 0을 꼭 추가해야 한다 (안하면 네트워크 연결 전에 마운트 시도해서 부팅 안 됨)
Cloudflare 연동 IP 등록
- 일본 특성상 IPv4 포트가 매우 제한적으로 열려 있고, 10000번대 밑으로는 아예 열리지도 않음
- IPv6는 이런 제한이 없음. 공유기가 각각의 머신에 뿌려주는 IP는 DHCP라기보다는 일본 인터넷에 직접 연결된 공인 IP.
- IPv6는 설계시부터 모든 기기가 고유의 공인 IP를 갖는 형태로 설계됨. 다만 그 특성상 보안에 취약하므로, 영구 IPv6 주소와 별개로 임시 IPv6가 부여되어, 수시로 주소가 바뀜.
- 주소 바뀜을 체크하여, Cloudflare DNS에 등록해 주는 역할 (v6 레코드인 AAAA를 업데이트 함)
- 다음 파일을 alpine 서버의 /etc/init.d에 저장. (파일 이름 cloudflare-alpine.service)실제 업데이트를 수행하는 Python 파일을 위의 서비스 스크립트에 지정된 위치로 잘 저장
#!/sbin/openrc-run # $apk add python3 # $apk add py3-requests # Copy this file into /etc/init.d/ # Test by $rc-service cloudflare-alpine.service start # $rc-update add cloudflare-alpine.service # $rc-service cloudflare-alpine.service restart # $rc-update -u description="Update Cloudflare DNS" command="/usr/bin/python3 /root/cloudflare-alpine.py" pidfile="/var/run/cloudflare/cloudflare.pid" command_background="yes" depend() { need net need nfsmount need sshd after iptables } start_pre() { ebegin "Starting cloudflare" mkdir -p /var/run/cloudflare || return 1 }
#!/usr/bin/env python # -*- coding: utf-8 -*- import os import requests import json from time import sleep CLOUDFLARE_KEY = 'XXX' CLOUDFLARE_ZONE_ID = 'XXX' CLOUDFLARE_DNS_TOKEN = 'XXX' CLOUDFLARE_HEADER = { 'Authorization': 'Bearer {}'.format(CLOUDFLARE_DNS_TOKEN), 'Content-Type': 'application/json' } DNS_GET_URL = 'https://api.cloudflare.com/client/v4/zones/{}/dns_records'.format(CLOUDFLARE_ZONE_ID) device = 'eth0' addr_file = '/tmp/cloudflare.addr6' def check(): addr = '' try: with open(addr_file, 'r') as f: addr = f.read() except: pass get_addr_cmd = "ip -6 addr list scope global $device | " \ "grep -v ' fd' | " \ "grep -v 'deprecated' | " \ "grep -v 'mngtmpaddr' | " \ "head -n 2 | " \ "tail -n 1" new_addr = os.popen(get_addr_cmd).read() new_addr = new_addr.split()[1] new_addr = new_addr.split('/')[0] if addr == new_addr: print('same ip {}'.format(new_addr)) else: r = requests.get(DNS_GET_URL, headers=CLOUDFLARE_HEADER) j = json.loads(r.text) for item in j['result']: dns_put_url = DNS_GET_URL + '/' + item['id'] new_data = dict( type=item['type'], name=item['name'], content=new_addr, ) if item['type'] == 'AAAA': new_data['proxied'] = True requests.put(dns_put_url, data=json.dumps(new_data), headers=CLOUDFLARE_HEADER) elif item['type'] == 'TXT': new_data['content'] = 'v=spf1 {} ~all'.format(new_addr) requests.put(dns_put_url, data=json.dumps(new_data), headers=CLOUDFLARE_HEADER) with open(addr_file, 'w') as f: f.write(new_addr) f.close() print('updated ip {}'.format(new_addr)) while True: check() sleep(60)
- 그 후 서비스 등록
rc-update add cloudflare-alpine.service rc-service cloudflare-alpine.service restart rc-update -u
Nginx 웹 프록시
- Cloudflare로부터 오는 HTTPS 요청을 처리하여, 내부 서버에 전달
- 처음 도입 목적은 Cloudflare의 IPv6 over IPv4 기능을 이용하기 위함
- 생각해보니 외부/내부를 분리하여 보안성도 높아지고, 도커를 이용한 로드밸런서 구현 및 포트 번호 추상화가 가능해져 채택
- /etc/nginx/conf.d는 시놀로지에 config를 등록해 놓고 폴더째로 마운트
- wiki-proxy.conf 예시
- proxy_set_header를 설정해야 내부 서버에서 보이는 접속 요청 IP가 실제 사용자의 IP로 제대로 뜬다
- 내부 서버사이의 통신은 http로 하여 속도 향상 (방화벽 설정은 따로)
- TODO: upstream 요청 처리가 60초 이상 걸려도 취소 안 하게 설정하기? wiki의 restbase나 mathoid가 고장나는 이유가 이것 때문인 듯
server { listen 80; listen [::]:80; server_name wiki.dong-min.kim; location / { return 301 https://$server_name$request_uri; } } server { listen 443 ssl; listen [::]:443 ssl; ssl_certificate pem파일; ssl_certificate_key key파일; server_name wiki.dong-min.kim; server_tokens off; location / { 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 X-Forwarded-Host $server_name; proxy_set_header Client-IP $remote_addr; proxy_pass http://내부 서버 주소:포트; } }
웹 데몬
Nginx (도커)
역할
- HTTP 요청을 받아서
- 직접 처리(static)하거나
- PHP 인터프리터로 보내거나
- 다른 웹 데몬(Node.js, Python, ...)으로 다시 proxy한다
레포지토리
- https://hub.docker.com/_/nginx
- 1.17.8-alpine
컨테이너 설정
- 포트 설정
- (외부 노출 서버 Nginx Proxy 포트 설정):(그대로)
- 볼륨 설정
- htpasswd -> (비공개)/htpasswd
- passwd -> /etc/passwd
- www -> (비공개)/www/
- nginx/conf.d/ -> /etc/nginx/conf.d/
- nginx/nginx.conf -> /etc/nginx/nginx.conf
- 환경 변수
- (기본값)
인터프리터
PHP (도커)
역할
- PHP 데몬
- FPM(FastCGI Process Manager) 사용하여 동적 워커 생성
레포지토리
- 공식 레포지토리의 7.3.31-fpm-alpine3.14 기반
- 추가로 PHP 확장 기능을 설치하기 위해 Dockerfile 작성
- gd, mysqli, intl, @composer
- 이용한 라이브러리
- Dockerfile
- 도커 레포지토리
컨테이너 설정
- 포트 설정
- (비공개):9000
- 참고로 www.conf에서 다른 포트로 설정해도 php-fpm.d/zz-docker.conf에서 무조건 기본값으로 바꿈
- 볼륨 설정
- php.ini -> /usr/local/etc/php/php.ini
- www.conf -> /usr/local/etc/php-fpm.d/www.conf
- www.conf -> /usr/local/etc/php-fpm.d/www.conf.default
- www -> (비공개)/www/
- php-패스wd -> /이티시/패스wd
- 환경 변수
- (기본값)
php.ini 설정
- max_execution_time = 30
- max_input_time = 60
- memory_limit = 512M
- post_max_size = 10240M
- upload_max_filesize = 10240M
- default_socket_timeout = 30
- extension gd2, mysqli 활성화
www.conf 설정
- 여기 설정은 주로 미디어위키의 VisualEditor 확장 기능 + Math 수식 입력기를 사용할 때 Restbase 서버에 동시에 많은 요청을 보내는 것을 처리하기 위해 필요함
- pm.max_children = 16
- pm.start_servers = 16
- pm.min_spare_servers = 16
- pm.max_spare_servers = 16
- pm.process_idle_timeout = 30s
데이터베이스
MySQL (도커)
역할
- 워드프레스, 미디어위키에 사용하기 위한 범용 데이터베이스
레포지토리
컨테이너 설정
- 포트 설정
- (외부 노출 서버 Nginx Proxy 포트 설정 시작 번호-2):(그대로)
- 볼륨 설정
- MySQL 실제 DB 파일 폴더 -> /var/lib/mysql/
- mysql.cnf -> /etc/mysql/conf.d/mysql.cnf
- 환경 변수
- (기본값)
Cassandra (도커)
역할
- 미디어위키의 API 백엔드 Restbase에서 사용하기 위한 고성능 데이터베이스
레포지토리
컨테이너 설정
- 포트 설정
- (비공개):9042
- 볼륨 설정
- Cassandra 실제 DB 파일 폴더 -> /var/lib/cassandra/
- Cassandra 설정 폴더 -> /etc/cassandra/
- 환경 변수
- CASSANDRA_BROADCAST_ADDRESS = (호스트 주소 - 집 안의 NAS IP)
cassandra-env.sh 설정
- https://www.mediawiki.org/wiki/Parsoid/Setup/RESTBase 참고
- MAX_HEAP_SIZE="128M"
- HEAP_NEWSIZE="20M"
cassandra.yaml 설정
- https://www.mediawiki.org/wiki/Parsoid/Setup/RESTBase 참고
- key_cache_size_in_mb: 0
- concurrent_reads: 2
- concurrent_writes: 2
- rpc_server_type: hsha
- rpc_min_threads: 1
- rpc_max_threads: 1
- concurrent_compactors: 1
- compaction_throughput_mb_per_sec: 0
응용 프로그램(애플리케이션) - Nginx 종속
워드프레스 (파일)
역할
- 개인 포트폴리오
- https://dong-min.kim
wp-컨피그.php
- FTPS 설정 (SFTP가 아니다)
- 프록시된 요청을 처리하기 위한 추가 설정
- $_SERVER['HTTPS']='on'; 구절만 있으면 된다
- 나머지는 프록시 서버 측의 설정이 잘못된 상태일 때 필요했었다
define('FTP_HOST', '내부 서버 주소:내부 포트 번호'); define('FTP_USER', 'wp-ftps'); define('FTP_PASS', ''); define('FTP_SSL', true); define('FTP_BASE', '(비공개)/wordpress/'); define('FTP_CONTENT_DIR', '(비공개)/wp-content/'); define('FTP_PLUGIN_DIR ', '(비공개)/wp-content/plugins/'); if ($_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https') $_SERVER['HTTPS']='on'; // define('RELOCATE', true); // define('WP_HOME', 'https://dong-min.kim'); // define('WP_SITEURL', 'https://dong-min.kim'); /* if ( ! empty( $_SERVER['HTTP_X_FORWARDED_HOST'] ) ) { $_SERVER['HTTP_HOST'] = $_SERVER['HTTP_X_FORWARDED_HOST']; } */
미디어위키 (파일)
역할
확장 기능
- VisualEditor, Math, SyntaxHighlight
- VisualEditor와 Math를 연동할 때, 수식 편집기에서 동적 업데이트 횟수에 비례해서 서버가 느려지는 현상 발생
- Math 확장 기능에서 제공하는 MWLatexNode.js가 수식이 업데이트 될 때마다 과거 기록을 지우지 않고 전부 갖고 있는 버그가 원인
- 그 기록들도 매 번 의미없는 업데이트를 하느라 서버가 느려짐
- 임시 해결 방법
- Math 확장 기능의 modules/ve-math/ve.ce.MWLatexNode.js 파일의 맨 아래 쪽에 다음 항목을 추가하여, 강제 업데이트를 방지
- 이거 해도 새로 고침은 하지만, 적어도 Mathoid 서버에 새로 요청 하지는 않는다 (캐시 사용)
/** * @inheritdoc ve.ce.GeneratedContentNode */ ve.ce.MWLatexNode.prototype.onGeneratedContentNodeUpdate = function ( staged ) { // 꼼수... this.root가 있을 때만 업데이트함 // this.root가 있는 노드는 실제 글 속의 math 노드 (다이얼로그 속은 root 없음) if (this.root) this.update( undefined, staged ); };
Nginx config
server {
listen ?????;
listen [::]:?????;
server_name wiki.dong-min.kim;
access_log /var/log/nginx/wiki.access.log main;
error_log /var/log/nginx/wiki.error.log;
charset utf-8;
root ?????;
index index.html index.htm index.php;
client_max_body_size 10240M;
# Avoid 504 HTTP Timeout Errors
proxy_connect_timeout 605;
proxy_send_timeout 605;
proxy_read_timeout 605;
send_timeout 605;
keepalive_timeout 605;
fastcgi_read_timeout 605;
location ~ ^/w/(index|load|thumb|opensearch_desc|api|rest|img_auth)\.php$ {
include fastcgi.conf;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_pass ?????:?????;
}
# Images
location /w/images {
# Separate location for images/ so .php execution won't apply
try_files $uri 404;
}
location /w/images/deleted {
# Deny access to deleted images folder
deny all;
}
# MediaWiki assets (usually images)
location ~ ^/w/resources/(assets|lib|src) {
try_files $uri 404;
add_header Cache-Control "public";
expires 7d;
}
# Assets, scripts and styles from skins and extensions
location ~ ^/w/(skins|extensions)/.+\.(css|js|gif|jpg|jpeg|png|svg)$ {
try_files $uri 404;
add_header Cache-Control "public";
expires 7d;
}
# License and credits files
location ~ ^/w/(COPYING|CREDITS)$ {
default_type text/plain;
}
## Uncomment the following code if you wish to use the installer/updater
## installer/updater
# location /w/mw-config/ {
# # Do this inside of a location so it can be negated
# location ~ \.php$ {
# include fastcgi.conf;
# fastcgi_param SCRIPT_FILENAME $document_root/w/mw-config/$fastcgi_script_name;
# fastcgi_pass ?????:????; # or whatever port your PHP-FPM listens on
# }
# }
# Handling for Mediawiki REST API, see [[mw:API:REST_API]]
location /w/rest.php/ {
try_files $uri $uri/ /w/rest.php?$query_string;
}
# Handling for the article path (pretty URLs)
location /view/ {
rewrite ^/view/(?<pagename>.*)$ /w/index.php;
}
# Allow robots.txt in case you have one
location = /robots.txt {
}
location = /favicon.ico {
}
location / {
rewrite ^/(.*)$ /view/$1 redirect;
}
}
LocalSettings.php
<?php
// ... (생략)
$wgArticlePath = "/view/$1";
$wgUsePathInfo = true;
$wgScriptExtension = ".php";
$wgMathValidModes[] = 'mathml';
$wgDefaultUserOptions['math'] = 'mathml';
$wgMathFullRestbaseURL = 'https://wiki-restbase.dong-min.kim/wiki.dong-min.kim/';
$wgMathMathMLUrl = 'https://wiki-mathoid.dong-min.kim';
# START VisualEditor Setting
$wgGroupPermissions['user']['writeapi'] = true;
wfLoadExtension( 'Parsoid', 'vendor/wikimedia/parsoid/extension.json' );
# END VisualEditor Setting
?>
미디어위키 Restbase (도커)
- 이 Restbase를 비롯하여 아래의 Parsoid, Mathoid는 미디어위키에서 Visual Editor + Math 확장 기능을 사용하기 위해 설치함
- 원래 미디어위키에서 무료로 제공하는 기본 Restbase서버와 Mathoid 서버를 이용해도 되지만, 속도가 정말 끔찍하게 느려서 직접 구축
- 제대로 된 문서가 없어서 구축 삽질 엄청 했다... 코드 안에 mediawiki url 하드코딩이 너무 많아 뭐가 문제인지 발견하기가 힘들었다
역할
- 미디어위키의 API를 처리하기 위한 REST 처리 서버
- REST로 받은 요청을 내부 독립 서버 (Parsoid, Mathoid 등)에 전달 및 반환 결과 캐싱
- 기본 DB 세팅인 SQLite는 동시에 많은 요청이 들어오면 db파일이 죽는 경우가 있어서, Cassandra 세팅으로 바꿈
- Node.js
레포지토리
- 인터넷에 떠도는 Dockerfile 기반으로 몇 가지 하드코딩을 넣어 이미지 생성
- Dockerfile
- Restbase 소스 (하드코딩 + 버그 수정)
- 도커 레포지토리
컨테이너 설정
- 포트 설정
- (비공개):7231
- 볼륨 설정
- config.yaml -> /mount/config.yaml
- 환경 변수
- (기본값)
미디어위키 Parsoid (도커)
역할
- 미디어위키의 Visual Editor 등에서 html <-> wikitext 간 변환 등을 위해 문서 실시간 파싱 등을 처리
- Node.js
레포지토리
- 인터넷에 떠도는 Dockerfile 기반으로 몇 가지 하드코딩을 넣어 이미지 생성
- Dockerfile
- Restbase 소스 (하드코딩 + 버그 수정)
- 도커 레포지토리
컨테이너 설정
- 포트 설정
- (비공개):8000
- (비공개):8001
- 볼륨 설정
- config.yaml -> /mount/config.yaml
- 환경 변수
- (기본값)
미디어위키 Mathoid (도커)
역할
- 미디어위키의 Math 확장 기능에서 사용
- LaTeX 문법을 svg, png 등으로 변환
- Node.js 10
- pm2로 서비스화 시킴
레포지토리
- 인터넷에 떠도는 Dockerfile 기반으로 몇 가지 하드코딩을 넣어 이미지 생성
- Dockerfile
- Restbase 소스 (하드코딩 + 버그 수정)
- 도커 레포지토리
컨테이너 설정
- 포트 설정
- (비공개):10042
- 볼륨 설정
- config.yaml -> /mount/config.yaml
- 환경 변수
- (기본값)
Deluge (토렌트) (도커)
역할
- 토렌트 서버
- 컨테이너를 완전히 OpenVPN으로 감싸서, VPN 등록이 되지 않은 상태에서는 네트워크 접속을 원천 차단
- *.ovpn 파일은 config 폴더에 넣으면 됨
- vpn 서버의 IP 주소를 찾지 못하므로, /etc/hosts에 수동으로 IP주소 써 주기
- (일본 한정) v6플러스의 포트 포화를 막기 위해, 토렌트 속도를 희생하고 timeout이 없는 UDP가 아닌 timeout도 있고 공유기가 IP 마스커레이드도 잘 해주는 TCP로 vpn 설정
레포지토리
컨테이너 설정
- 포트 설정
- (기본값)
- 볼륨 설정
- config/ -> /config
- (자료 저장 폴더) -> /data
- 환경 변수
- NAME_SERVERS = 1.1.1.1
- LAN_NETWORK = 호스트의 아이피 말고 호스트의 서브넷 (xxx.xxx.xxx.xxx/xx)
- ENABLE_PRIVOXY = yes
- PGID = 100
- PUID = 1026
- VPN_PROV = custom
- VPN_ENABLED = yes
- HOME = /config/home
Gitlab
역할
- 사설 Git 서버
레포지토리
컨테이너 설정
- 포트 설정
- (비공개):22
- (비공개):80
- (비공개):443
- (비공개):5005
- 볼륨 설정
- gitlab 실제 자료 폴더 -> /var/opt/gitlab/
- gitlab 설정 폴더 -> /etc/gitlab/
gitlab.rb 설정
- external_url 'https://git.dong-min.kim'
- gitlab_rails['gitlab_ssh_host'] = 'kasumi.synology.me'
- gitlab_rails['time_zone'] = 'Asia/Seoul'
- gitlab_rails['gitlab_default_theme'] = 10 # dark(default) = 2, red = 9, light red = 10
- gitlab_rails['trusted_proxies'] = ['시놀로지IP', '프록시IP']
- gitlab_rails['gitlab_shell_ssh_port'] = 64100
- registry_external_url 'https://registry.dong-min.kim'
- gitlab_rails['registry_enabled'] = true
- unicorn['worker_processes'] = 2
- sidekiq['concurrency'] = 3 # default 25
- nginx['gzip_enabled'] = false
- nginx['listen_port'] = 80
- nginx['listen_https'] = false
- registry_nginx['enable'] = true
- registry_nginx['gzip_enabled'] = false
- registry_nginx['listen_port'] = 5005
- registry_nginx['listen_https'] = false
업데이트
- 업그레이드 패스 참조: https://gitlab-com.gitlab.io/support/toolbox/upgrade-path/
- 컨테이너 들어가기
- 서비스 중지
- gitlab-ctl stop
- 컨테이너 정지
- 컨테이너 삭제
- 새 컨테이너 생성
- (비공개):80
- (비공개):443
- (비공개):22
- (비공개):5005
- gitlab 실제 자료 폴더 -> /var/opt/gitlab/
- gitlab 설정 폴더 -> /etc/gitlab/
- 상태 확인: https://git.dong-min.kim/admin/background_migrations
- 최종 확인
- gitlab-rake gitlab:check
Gitlab Runner
역할
- Gitlab의 CI/CD 실행용 Runner
레포지토리
컨테이너 설정
- 파일 설정
- docker.sock -> /var/run/docker.sock
- 볼륨 설정
- gitlab runner 설정 폴더 -> /etc/gitlab-runner
- 주의점
- 시놀로지 docker를 쓰려면 시놀로지의 docker.sock이 필요하다.
- 먼저 시놀로지 측에서 sudo ln -s /var/run/docker.sock /volume1/docker/docker.sock 으로 심볼릭 링크 생성
- Gitlab Runner 컨테이너 생성할 때 위 파일 링크가 안 됨
- 먼저 아무 파일이나 링크해서 일단 컨테이너 생성
- 컨테이너 설정 백업해서, 그 파일 안에서 링크 수정
- 수정한 컨테이너 설정을 다시 로드
- 컨테이너 실행 후 gitlab-runner register 명령어로 gitlab 등록
- 시놀로지 docker를 쓰려면 시놀로지의 docker.sock이 필요하다.
kb_apart (광규 외주) (도커)
역할
- 광규 외주 프로그램 - 아파트 시세 확인
- gliderlabs/alpine:3.3 기반 (glibc 설치용)
- Miniconda3 설치
- Python 3.7.5 + Flask
레포지토리
- Dockerfile
- 도커 레포지토리 없음 (비공개 코드)
- tar 파일로 직접 업로드
컨테이너 설정
- 포트 설정
- (비공개):5000
- 볼륨 설정
- 법정동.txt -> /var/lib/kb_apart/utils/법정동.txt
- 환경 변수
- CONDA_ENV_NAME = kb_apart
Internet Speed Logger (도커)
역할
- 일정 주기마다 Speedtest 사이트로 속도 측정해서 그래프로 표시
- 자꾸 집 인터넷 QoS 걸리는 것 같아서 설치함
레포지토리
컨테이너 설정
- 포트 설정
- (비공개):3000
- 볼륨 설정
- internet speed logger 설정 폴더 -> /usr/src/app/data
- 환경 변수
- CHECK_PERIOD_MINUTES = 30
응용 프로그램(애플리케이션) - 독립형
busybox (도커)
역할
- 도커 게스트 관점에서 바라보는 파일 권한 확인, 간단한 명령어 (curl이나 ping 등) 실행용
레포지토리
- https://hub.docker.com/_/busybox
- 1.31.1-glibc
컨테이너 설정
- 포트 설정
- (없음)
- 볼륨 설정
- www -> (비공개)/www/
- 환경 변수
- (기본값)
openvpn (도커)
역할
- OpenVPN Client 를 수행해서, 그 결과를 SOCKS5 프록시 서버로 통신 가능
- OpenVPN to SOCKS5/HTTP Proxy Docker Image
- 시놀로지 도커에서 자꾸 IPV6 설정 실패하니, ovpn 파일 안의
- ovpn 파일 안에 proto udp를 proto udp4로
- setenv UV_IPV6 yes 주석처리
레포지토리
컨테이너 설정
- 포트 설정
- (비공개):1080 tcp
- (비공개):1080 udp
- 볼륨 설정
- (openvpn 설정폴더)/vpn -> /vpn
- /dev/net/tun -> /dev/net/tun (필요없을수도?)
- 환경 변수
- OPENVPN_CONFIG = /vpn/설정파일.ovpn
권한 관련 팁
Nginx, PHP의 404 Not found 오류는 권한 문제일 때가 많다. 도커에서 실행중이라고 했을 때 살펴볼 것은
- 컨테이너 내에서 Nginx나 PHP를 실행하고 있는 uid는 무엇인가?
- 해당 uid가 파일을 읽을 수 있는가? 쓸 수 있는가?
- uid가 속해 있는 그룹 확인 (gid)
- 해당 gid가 파일을 읽을 수 있는가? 쓸 수 있는가?
- 권한이 있는데도 접근이 안 되는 경우
- 루트 디렉터리에서부터 시작해서, 해당 파일이 있는 디렉터리까지의 경로까지 중에서 현재 uid 또는 gid로 실행 권한을 얻을 수 있는지 확인할 것.
- 읽기, 쓰기 권한이 아니라 실행 권한이다.
- 겉으로 보기에는 같은 www-data이더라도 컨테이너에 따라 id는 다를 수 있다.
- 시놀로지의 경우 NFS 서버로 마운트한 클라이언트에서 본 권한과도 다를 수 있기 때문에 주의
- LDAP 설정해서 동기화 하려 했으나 귀찮아서 일단 보류
집 Docker Swarm 삽질
GUI 프로그램
Portainer (9000)
- 가능
- gitlab 연동 가능
- gitlab 레지스트리에서 이미지 push/pull 가능
- 터미널 실행 가능
- 불가
- gitlab 레지스트리 목록 보기 불가
- 이미지에서 마우스로 컨테이너 실행 불가
Swarmpit (888)
- 가능
- gitlab 연동 가능
- gitlab 레지스트리에서 이미지 push/pull 가능
- gitlab 레지스트리 목록 보기 가능
- 이미지에서 마우스로 컨테이너 실행 가능
- 불가
- 터미널 실행 불가