Commit 41d4d0b9 authored by insun park's avatar insun park
Browse files

docker/README.md 및 docker 하위 프로젝트 일괄 추가

parent c384e1fe
# Flask 기반 HTTPS 리버스 프록시
이 프로젝트는 Flask를 사용하여 특정 URL로의 요청을 대신 전달해주는 간단한 HTTPS 리버스 프록시 서버를 Docker로 실행합니다.
## 주요 기능
- **프록시**: `/proxy?url=<TARGET_URL>` 형식으로 요청을 받아 `<TARGET_URL>`로 요청을 전달하고 응답을 반환합니다.
- **HTTPS 지원**: 제공된 SSL 인증서를 사용하여 HTTPS 서버로 동작합니다.
- **CORS 지원**: 모든 출처(`*`)에 대해 CORS(Cross-Origin Resource Sharing)를 허용합니다.
- **HTTP to HTTPS 리다이렉트**: 모든 HTTP 요청을 자동으로 HTTPS로 리다이렉트합니다.
- **로깅**: 모든 프록시 활동과 오류를 `proxy_app.log` 파일에 기록합니다.
## 사전 요구사항
- [Docker](https://www.docker.com/get-started)
- [Docker Compose](https://docs.docker.com/compose/install/)
- **SSL 인증서**: HTTPS 서비스를 위해 유효한 SSL 인증서 파일(`cert.pem`)과 개인 키 파일(`privkey.pem`)이 필요합니다.
## 사용 방법
### 1. SSL 인증서 준비
프로젝트 루트 디렉토리에 `proxy.geumdo.net` 폴더를 생성하고, 내부에 `cert.pem``privkey.pem` 파일을 위치시킵니다.
```
.
├── Dockerfile
├── app.py
├── docker-compose.yml
└── proxy.geumdo.net/
├── cert.pem <-- 여기에 인증서 파일
└── privkey.pem <-- 여기에 개인 키 파일
```
### 2. 서비스 시작 및 빌드
아래 스크립트를 실행하여 Docker 이미지를 빌드하고 컨테이너를 시작합니다.
```bash
./rebuild_docker.sh
```
이 스크립트는 `docker-compose.yml` 설정을 사용하여 컨테이너를 백그라운드에서 실행합니다.
## 서비스 접속 정보
- **서비스 포트**: 호스트의 `3001`번 포트가 컨테이너의 `3000`번 포트로 매핑됩니다.
- **엔드포인트**: `https://<서버_IP>:3001/proxy`
### 사용 예시
`https://www.google.com` 으로 프록시 요청을 보내려면 아래와 같이 호출합니다.
```
https://<서버_IP>:3001/proxy?url=https://www.google.com
```
## 코드 수정 및 반영
이 프로젝트는 로컬의 `app.py` 파일을 컨테이너 내부로 직접 마운트합니다. 따라서 `app.py` 파일의 내용을 수정한 후, 아래 명령어로 컨테이너를 재시작하면 변경 사항이 즉시 반영됩니다.
```bash
docker-compose restart
```
\ No newline at end of file
import logging
from flask import Flask, request, Response, stream_with_context
from flask_cors import CORS
import requests
import os
from werkzeug.middleware.proxy_fix import ProxyFix
app = Flask(__name__)
app.wsgi_app = ProxyFix(app.wsgi_app) # ProxyFix 미들웨어 추가
CORS(app, resources={r"/*": {"origins": "*"}}) # 모든 출처에 대해 CORS를 활성화합니다.
# 로그 디렉터리 및 파일 설정
log_dir = '/app'
if not os.path.exists(log_dir):
os.makedirs(log_dir) # 로그 디렉터리가 없으면 생성
log_file = os.path.join(log_dir, 'proxy_app.log')
# 로깅 설정
logging.basicConfig(filename=log_file, level=logging.DEBUG,
format='%(asctime)s %(levelname)s %(name)s %(threadName)s : %(message)s')
app.logger.addHandler(logging.StreamHandler())
app.logger.setLevel(logging.DEBUG)
@app.before_request
def before_request():
if request.scheme == 'http':
# HTTP 요청을 HTTPS로 리다이렉트
return Response(f"Redirecting to HTTPS: {request.url.replace('http://', 'https://')}",
status=301,
headers={'Location': request.url.replace('http://', 'https://')})
@app.route('/proxy', methods=['GET', 'POST', 'PUT', 'DELETE'])
def proxy_prusa_link():
try:
# 쿼리 파라미터에서 URL 가져오기
url = request.args.get('url')
if not url:
return Response("URL is required", status=400)
# 타겟 URL에 대한 요청 준비
headers = {key: value for key, value in request.headers.items() if key != 'Host'}
response = requests.request(
method=request.method,
url=url,
headers=headers,
data=request.get_data(),
cookies=request.cookies,
stream=True # 스트리밍 응답 활성화
)
# 응답을 클라이언트로 스트리밍
def generate():
for chunk in response.iter_content(chunk_size=8192):
yield chunk
proxy_response = Response(stream_with_context(generate()), status=response.status_code)
for key, value in response.headers.items():
if key.lower() != 'content-encoding' and key.lower() != 'transfer-encoding':
proxy_response.headers[key] = value
return proxy_response
except Exception as e:
app.logger.error(f"An error occurred: {str(e)}") # 에러 로그 기록
return Response(f"An error occurred: {str(e)}", status=500)
if __name__ == '__main__':
# SSL 인증서와 키 파일 경로 설정
context = ('./proxy.geumdo.net/cert.pem', './proxy.geumdo.net/privkey.pem')
app.run(host='0.0.0.0', port=3000, debug=True, ssl_context=context) # SSL 컨텍스트 추가
version: '3'
services:
os:
build:
context: .
dockerfile: Dockerfile
container_name: docker_flask_proxy
ports:
- "3001:3000" # SSH
network_mode: bridge
restart: always
volumes:
- ./app.py:/app/app.py
- ./proxy_app.log:/app/proxy_app.log
- ./proxy.geumdo.net/:/app/proxy.geumdo.net/
This directory contains your keys and certificates.
`privkey.pem` : the private key for your certificate.
`fullchain.pem`: the certificate file used in most server software.
`chain.pem` : used for OCSP stapling in Nginx >=1.3.7.
`cert.pem` : will break many server configurations, and should not be used
without reading further documentation (see link below).
WARNING: DO NOT MOVE OR RENAME THESE FILES!
Certbot expects these files to remain in this location in order
to function properly!
We recommend not moving these files. For more information, see the Certbot
User Guide at https://certbot.eff.org/docs/using.html#where-are-my-certificates.
-----BEGIN CERTIFICATE-----
MIIE8DCCA9igAwIBAgISBBfP7j3SinMv6vnXQKHMxaNqMA0GCSqGSIb3DQEBCwUA
MDMxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MQwwCgYDVQQD
EwNSMTEwHhcNMjQxMDEwMDc0NTM1WhcNMjUwMTA4MDc0NTM0WjAbMRkwFwYDVQQD
ExBwcm94eS5nZXVtZG8ubmV0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
AQEAwNxj2VpmMSaq8NY1dRwT1ioqShwdKrTUmjQNRyzeXDCFnXIcrDXrhxsY0n4F
+KzIVYYghh31nbCW841bPdhC5QDC3IHHze02L+uJrU+DwVYFxrHS+1Su06NBn3Ok
MsRIzqtlBHbGLzihhG8Ky9faKhW5mpccVzbF6PI11/vZFRO87pCty3/YhCH2CE4P
Uck4iwmbCw6nQ1wgj0dg3n3YsE7+YTMd6Aybs4e+Zm8hHiZ3rVvBfJwRzwJ+NfBD
CiLjwu65sxh1f/6rcRCUMn0Le+l3rVUZUZe8aEZaCOvHwo+S1OXcWKfsr832lknv
RHu6FEbecC+8Jfy+Gw0IT2NWwQIDAQABo4ICFDCCAhAwDgYDVR0PAQH/BAQDAgWg
MB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAMBgNVHRMBAf8EAjAAMB0G
A1UdDgQWBBSGYt+USwQBQdzdkB7EymXUSqKSNzAfBgNVHSMEGDAWgBTFz0ak6vTD
wHpslcQtsF6SLybjuTBXBggrBgEFBQcBAQRLMEkwIgYIKwYBBQUHMAGGFmh0dHA6
Ly9yMTEuby5sZW5jci5vcmcwIwYIKwYBBQUHMAKGF2h0dHA6Ly9yMTEuaS5sZW5j
ci5vcmcvMBsGA1UdEQQUMBKCEHByb3h5LmdldW1kby5uZXQwEwYDVR0gBAwwCjAI
BgZngQwBAgEwggEEBgorBgEEAdZ5AgQCBIH1BIHyAPAAdQA/F0tP1yJHWJQdZRyE
vg0S7ZA3fx+FauvBvyiF7PhkbgAAAZJ1mXtSAAAEAwBGMEQCIE3TjBbdrgvnvHuU
BEUR4Z5VnjVmLcbIp3sJTq+vLdLOAiB9KrRxb1hP1UvGMW9h7pt25rcQqYvM+M1L
BfuNzLmRBQB3AOCSs/wMHcjnaDYf3mG5lk0KUngZinLWcsSwTaVtb1QEAAABknWZ
fZYAAAQDAEgwRgIhANlEtFaEYYMFApWBLA8JE31AGZzb/DXUEb3wsLOWSDJMAiEA
12Xsdy+oz2TYWMEH/Xx4GnhL30WmYk3crI3GtkA4eq0wDQYJKoZIhvcNAQELBQAD
ggEBAHdwGGQamaOTe9Zafn095Jn290hVGPeuhUiLq12kYAOTwNM1iiX9UUbnx3zx
/oUCpRcvMMcYGGCBP69lgwb06tMwcreNs9iIh5S9zRhUuWawa/9hgsDLOkXoU+rR
JeyKwy11SoKap5rJZP3dtOOVoTKMtXe5tc/G0UemQ+M1HROviM2WhlJCMBSzwF1u
znkCcwZ+KWxDndIQNq5/OPy5bkhQcR/FHv/y/aQIzr2toiy5fk7lmIQZ7DjXlF3Y
gU/dSe9rn3hGhybTvobMS/RQIvBKW6hjzeZk/sIubWr55RXg0h345YwzlHzlGTED
OZmCSkuDc+bJJSlhlMjt9BwTTAI=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIFBjCCAu6gAwIBAgIRAIp9PhPWLzDvI4a9KQdrNPgwDQYJKoZIhvcNAQELBQAw
TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMjQwMzEzMDAwMDAw
WhcNMjcwMzEyMjM1OTU5WjAzMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNTGV0J3Mg
RW5jcnlwdDEMMAoGA1UEAxMDUjExMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
CgKCAQEAuoe8XBsAOcvKCs3UZxD5ATylTqVhyybKUvsVAbe5KPUoHu0nsyQYOWcJ
DAjs4DqwO3cOvfPlOVRBDE6uQdaZdN5R2+97/1i9qLcT9t4x1fJyyXJqC4N0lZxG
AGQUmfOx2SLZzaiSqhwmej/+71gFewiVgdtxD4774zEJuwm+UE1fj5F2PVqdnoPy
6cRms+EGZkNIGIBloDcYmpuEMpexsr3E+BUAnSeI++JjF5ZsmydnS8TbKF5pwnnw
SVzgJFDhxLyhBax7QG0AtMJBP6dYuC/FXJuluwme8f7rsIU5/agK70XEeOtlKsLP
Xzze41xNG/cLJyuqC0J3U095ah2H2QIDAQABo4H4MIH1MA4GA1UdDwEB/wQEAwIB
hjAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwEgYDVR0TAQH/BAgwBgEB
/wIBADAdBgNVHQ4EFgQUxc9GpOr0w8B6bJXELbBeki8m47kwHwYDVR0jBBgwFoAU
ebRZ5nu25eQBc4AIiMgaWPbpm24wMgYIKwYBBQUHAQEEJjAkMCIGCCsGAQUFBzAC
hhZodHRwOi8veDEuaS5sZW5jci5vcmcvMBMGA1UdIAQMMAowCAYGZ4EMAQIBMCcG
A1UdHwQgMB4wHKAaoBiGFmh0dHA6Ly94MS5jLmxlbmNyLm9yZy8wDQYJKoZIhvcN
AQELBQADggIBAE7iiV0KAxyQOND1H/lxXPjDj7I3iHpvsCUf7b632IYGjukJhM1y
v4Hz/MrPU0jtvfZpQtSlET41yBOykh0FX+ou1Nj4ScOt9ZmWnO8m2OG0JAtIIE38
01S0qcYhyOE2G/93ZCkXufBL713qzXnQv5C/viOykNpKqUgxdKlEC+Hi9i2DcaR1
e9KUwQUZRhy5j/PEdEglKg3l9dtD4tuTm7kZtB8v32oOjzHTYw+7KdzdZiw/sBtn
UfhBPORNuay4pJxmY/WrhSMdzFO2q3Gu3MUBcdo27goYKjL9CTF8j/Zz55yctUoV
aneCWs/ajUX+HypkBTA+c8LGDLnWO2NKq0YD/pnARkAnYGPfUDoHR9gVSp/qRx+Z
WghiDLZsMwhN1zjtSC0uBWiugF3vTNzYIEFfaPG7Ws3jDrAMMYebQ95JQ+HIBD/R
PBuHRTBpqKlyDnkSHDHYPiNX3adPoPAcgdF3H2/W0rmoswMWgTlLn1Wu0mrks7/q
pdWfS6PJ1jty80r2VKsM/Dj3YIDfbjXKdaFU5C+8bhfJGqU3taKauuz0wHVGT3eo
6FlWkWYtbt4pgdamlwVeZEW+LM7qZEJEsMNPrfC03APKmZsJgpWCDWOKZvkZcvjV
uYkQ4omYCTX5ohy+knMjdOmdH9c7SpqEWBDC86fiNex+O0XOMEZSa8DA
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIE8DCCA9igAwIBAgISBBfP7j3SinMv6vnXQKHMxaNqMA0GCSqGSIb3DQEBCwUA
MDMxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MQwwCgYDVQQD
EwNSMTEwHhcNMjQxMDEwMDc0NTM1WhcNMjUwMTA4MDc0NTM0WjAbMRkwFwYDVQQD
ExBwcm94eS5nZXVtZG8ubmV0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
AQEAwNxj2VpmMSaq8NY1dRwT1ioqShwdKrTUmjQNRyzeXDCFnXIcrDXrhxsY0n4F
+KzIVYYghh31nbCW841bPdhC5QDC3IHHze02L+uJrU+DwVYFxrHS+1Su06NBn3Ok
MsRIzqtlBHbGLzihhG8Ky9faKhW5mpccVzbF6PI11/vZFRO87pCty3/YhCH2CE4P
Uck4iwmbCw6nQ1wgj0dg3n3YsE7+YTMd6Aybs4e+Zm8hHiZ3rVvBfJwRzwJ+NfBD
CiLjwu65sxh1f/6rcRCUMn0Le+l3rVUZUZe8aEZaCOvHwo+S1OXcWKfsr832lknv
RHu6FEbecC+8Jfy+Gw0IT2NWwQIDAQABo4ICFDCCAhAwDgYDVR0PAQH/BAQDAgWg
MB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAMBgNVHRMBAf8EAjAAMB0G
A1UdDgQWBBSGYt+USwQBQdzdkB7EymXUSqKSNzAfBgNVHSMEGDAWgBTFz0ak6vTD
wHpslcQtsF6SLybjuTBXBggrBgEFBQcBAQRLMEkwIgYIKwYBBQUHMAGGFmh0dHA6
Ly9yMTEuby5sZW5jci5vcmcwIwYIKwYBBQUHMAKGF2h0dHA6Ly9yMTEuaS5sZW5j
ci5vcmcvMBsGA1UdEQQUMBKCEHByb3h5LmdldW1kby5uZXQwEwYDVR0gBAwwCjAI
BgZngQwBAgEwggEEBgorBgEEAdZ5AgQCBIH1BIHyAPAAdQA/F0tP1yJHWJQdZRyE
vg0S7ZA3fx+FauvBvyiF7PhkbgAAAZJ1mXtSAAAEAwBGMEQCIE3TjBbdrgvnvHuU
BEUR4Z5VnjVmLcbIp3sJTq+vLdLOAiB9KrRxb1hP1UvGMW9h7pt25rcQqYvM+M1L
BfuNzLmRBQB3AOCSs/wMHcjnaDYf3mG5lk0KUngZinLWcsSwTaVtb1QEAAABknWZ
fZYAAAQDAEgwRgIhANlEtFaEYYMFApWBLA8JE31AGZzb/DXUEb3wsLOWSDJMAiEA
12Xsdy+oz2TYWMEH/Xx4GnhL30WmYk3crI3GtkA4eq0wDQYJKoZIhvcNAQELBQAD
ggEBAHdwGGQamaOTe9Zafn095Jn290hVGPeuhUiLq12kYAOTwNM1iiX9UUbnx3zx
/oUCpRcvMMcYGGCBP69lgwb06tMwcreNs9iIh5S9zRhUuWawa/9hgsDLOkXoU+rR
JeyKwy11SoKap5rJZP3dtOOVoTKMtXe5tc/G0UemQ+M1HROviM2WhlJCMBSzwF1u
znkCcwZ+KWxDndIQNq5/OPy5bkhQcR/FHv/y/aQIzr2toiy5fk7lmIQZ7DjXlF3Y
gU/dSe9rn3hGhybTvobMS/RQIvBKW6hjzeZk/sIubWr55RXg0h345YwzlHzlGTED
OZmCSkuDc+bJJSlhlMjt9BwTTAI=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIFBjCCAu6gAwIBAgIRAIp9PhPWLzDvI4a9KQdrNPgwDQYJKoZIhvcNAQELBQAw
TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMjQwMzEzMDAwMDAw
WhcNMjcwMzEyMjM1OTU5WjAzMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNTGV0J3Mg
RW5jcnlwdDEMMAoGA1UEAxMDUjExMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
CgKCAQEAuoe8XBsAOcvKCs3UZxD5ATylTqVhyybKUvsVAbe5KPUoHu0nsyQYOWcJ
DAjs4DqwO3cOvfPlOVRBDE6uQdaZdN5R2+97/1i9qLcT9t4x1fJyyXJqC4N0lZxG
AGQUmfOx2SLZzaiSqhwmej/+71gFewiVgdtxD4774zEJuwm+UE1fj5F2PVqdnoPy
6cRms+EGZkNIGIBloDcYmpuEMpexsr3E+BUAnSeI++JjF5ZsmydnS8TbKF5pwnnw
SVzgJFDhxLyhBax7QG0AtMJBP6dYuC/FXJuluwme8f7rsIU5/agK70XEeOtlKsLP
Xzze41xNG/cLJyuqC0J3U095ah2H2QIDAQABo4H4MIH1MA4GA1UdDwEB/wQEAwIB
hjAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwEgYDVR0TAQH/BAgwBgEB
/wIBADAdBgNVHQ4EFgQUxc9GpOr0w8B6bJXELbBeki8m47kwHwYDVR0jBBgwFoAU
ebRZ5nu25eQBc4AIiMgaWPbpm24wMgYIKwYBBQUHAQEEJjAkMCIGCCsGAQUFBzAC
hhZodHRwOi8veDEuaS5sZW5jci5vcmcvMBMGA1UdIAQMMAowCAYGZ4EMAQIBMCcG
A1UdHwQgMB4wHKAaoBiGFmh0dHA6Ly94MS5jLmxlbmNyLm9yZy8wDQYJKoZIhvcN
AQELBQADggIBAE7iiV0KAxyQOND1H/lxXPjDj7I3iHpvsCUf7b632IYGjukJhM1y
v4Hz/MrPU0jtvfZpQtSlET41yBOykh0FX+ou1Nj4ScOt9ZmWnO8m2OG0JAtIIE38
01S0qcYhyOE2G/93ZCkXufBL713qzXnQv5C/viOykNpKqUgxdKlEC+Hi9i2DcaR1
e9KUwQUZRhy5j/PEdEglKg3l9dtD4tuTm7kZtB8v32oOjzHTYw+7KdzdZiw/sBtn
UfhBPORNuay4pJxmY/WrhSMdzFO2q3Gu3MUBcdo27goYKjL9CTF8j/Zz55yctUoV
aneCWs/ajUX+HypkBTA+c8LGDLnWO2NKq0YD/pnARkAnYGPfUDoHR9gVSp/qRx+Z
WghiDLZsMwhN1zjtSC0uBWiugF3vTNzYIEFfaPG7Ws3jDrAMMYebQ95JQ+HIBD/R
PBuHRTBpqKlyDnkSHDHYPiNX3adPoPAcgdF3H2/W0rmoswMWgTlLn1Wu0mrks7/q
pdWfS6PJ1jty80r2VKsM/Dj3YIDfbjXKdaFU5C+8bhfJGqU3taKauuz0wHVGT3eo
6FlWkWYtbt4pgdamlwVeZEW+LM7qZEJEsMNPrfC03APKmZsJgpWCDWOKZvkZcvjV
uYkQ4omYCTX5ohy+knMjdOmdH9c7SpqEWBDC86fiNex+O0XOMEZSa8DA
-----END CERTIFICATE-----
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDA3GPZWmYxJqrw
1jV1HBPWKipKHB0qtNSaNA1HLN5cMIWdchysNeuHGxjSfgX4rMhVhiCGHfWdsJbz
jVs92ELlAMLcgcfN7TYv64mtT4PBVgXGsdL7VK7To0Gfc6QyxEjOq2UEdsYvOKGE
bwrL19oqFbmalxxXNsXo8jXX+9kVE7zukK3Lf9iEIfYITg9RyTiLCZsLDqdDXCCP
R2DefdiwTv5hMx3oDJuzh75mbyEeJnetW8F8nBHPAn418EMKIuPC7rmzGHV//qtx
EJQyfQt76XetVRlRl7xoRloI68fCj5LU5dxYp+yvzfaWSe9Ee7oURt5wL7wl/L4b
DQhPY1bBAgMBAAECggEBAJEnDqtvA0zo6m06+575k+BzecKvaDBVS1IH7RptpanD
Bz1ZvkTKjEryVPtPyFTCTkE4ItBuSgb1+payBEMGuko7CW4G64eMimUEpGlhWCux
/8Ts33sz4CT/UYud8K4Y1yddDjmO31h5Ce9v17NV8SgNk9TK+JSXb9sEOQwmy9q0
4sdCwP9Vt/fQUXZCfmWjDPzctwe2EsbadezJ4lUaQHS+Lq0WZKYoRHZZz1a3QMp6
CXP7wJKpcaJikt8Rne/HGBh6pFZCSc4YDaTJwuJRFb/V7lAvfWeUjA4cqbbYOtT1
bCpIpVz3Y6H00Md8MAHOeVpVWYH898ByJuAwMLNth3UCgYEA4yRh7zKm12DRlxz0
UQ8jsLG0n408bLoTE0+10G44RXEHNMbOBLnI7YCdxBVb3PY2Mcy1VtuscuHntuXg
kNSpFlv1Z3hkMZFJDwjUPWSYMENKWlvQ6NOU3fbftF7/l37YrQ0KAicGiRINXyRf
vr2QRkfxwXUrz9pnt2s7gCWuk2cCgYEA2V0JtkmM1V4LElOX4BFYBi+c+Br4fhMx
zn0eXBTMjOJaqrM2pLkhVac01J5XhfpS77znrxQKjO7g5x6LqSvChA2iK6rqUyMq
iLzWPJLCLmB3o1tBAub/ARP7MrYn6DhgxeJS7LV27mg8NxMDvi31omlBcukjZZ23
Ji2oDwNgU5cCgYBGNFiQtfcbWrFtI2XgJ+3ADyzko6KpeFms/lYTtf1ueSDhDxFe
JI4V2kro8DEUeoUFn1/tGLiUSX506Vgfa5tXbdTLxkoxh9Ys722qDA193U593yMS
01KPyF4cQcB98pbF5eHSCH3cn9fCMFvneG+/ST1Prgd8luS3rE0Xro3mwQKBgF7n
76Cm9pYHDOCAnVSZXgy9Z1UxOYSazulw2fusnS96ecoEm/xKVRK4Aio/xMlb5jCF
E8fvAThN6OchACvqTnEoHsHgS5XnSeAQS56BGcX0Gui5pGYnA/qthcW7oSsUyrQ8
QKbYCMjJvFjztXOpT5INUSViRDFPLrO9xZ5ghAObAoGBAKiNltO5Cd9aw445JJJ6
kMoGjLsN6t6meQl8tzXAj8GMNxIy7UUaLdmcZ6GP6qPJvHaIceXWbDbts62Ys2/I
qfbMj+UodQ/xyv7CKd9WduLZoTFRuTntyCBhRVs8pINARMn6xeLV3LmcJf1U4V0C
BKlqAfYUZW9reVg3rWx+Bhmk
-----END PRIVATE KEY-----
#!/bin/sh
# Build Docker image with explicit build context and Dockerfile path
docker build -t .
# Run Docker Compose with a specific container name
docker-compose up -d --build
# GitLab CE (Community Edition) 서버
이 프로젝트는 Docker Compose를 사용하여 GitLab Community Edition (CE) 서버를 간편하게 배포하기 위한 설정입니다.
## 주요 기능
- **GitLab CE**: `gitlab/gitlab-ce` 공식 이미지를 사용하여 완전한 GitLab 환경을 제공합니다.
- **데이터 영속성**: GitLab의 설정, 로그, 데이터는 모두 호스트의 특정 디렉토리(`GITLAB_HOME`)에 마운트되어 영속적으로 관리됩니다.
- **HTTPS 기본 설정**: `gitlab.geumdo.net` 도메인에 대한 HTTPS 접속 및 HTTP에서 HTTPS로의 자동 리다이렉션이 미리 설정되어 있습니다.
## 사전 요구사항
- [Docker](https://www.docker.com/get-started)
- [Docker Compose](https://docs.docker.com/compose/install/)
- **도메인 및 DNS 설정**: GitLab 서버로 사용할 도메인(예: `gitlab.geumdo.net`)과 해당 도메인의 A 레코드가 서버 IP를 가리키도록 설정되어 있어야 합니다.
- **호스트 디렉토리**: GitLab 데이터를 저장할 호스트 디렉토리를 준비해야 합니다. 기본값은 `/srv/gitlab` 입니다.
- **SSL 인증서**: HTTPS 서비스를 위해 유효한 SSL 인증서가 필요합니다.
## 사용 방법
### 1. 환경 변수 및 디렉토리 설정
`.env` 파일은 `GITLAB_HOME``/srv/gitlab`으로 설정합니다. 다른 경로를 사용하려면 이 파일을 수정하거나 쉘 환경 변수를 직접 설정하십시오.
```bash
# 기본 경로인 /srv/gitlab 디렉토리 생성
mkdir -p /srv/gitlab
```
### 2. SSL 인증서 준비
HTTPS 접속을 위해 SSL 인증서와 키, dhparam 파일을 준비하여 GitLab 설정 디렉토리 내 `ssl` 폴더에 위치시켜야 합니다.
```bash
# /srv/gitlab/config/ssl 디렉토리 생성
mkdir -p /srv/gitlab/config/ssl
# 인증서 파일들을 해당 경로로 복사
# cp <your_fullchain.pem> /srv/gitlab/config/ssl/fullchain.pem
# cp <your_privkey.pem> /srv/gitlab/config/ssl/privkey.pem
# cp <your_dhparams.pem> /srv/gitlab/config/ssl/dhparams.pem # (선택 사항이지만 권장)
```
`docker-compose.yml`은 이 경로의 인증서를 사용하도록 설정되어 있습니다.
### 3. 서비스 시작
아래 명령어를 실행하여 GitLab 컨테이너를 시작합니다. 최초 실행 시 GitLab을 초기화하는 데 몇 분 정도 소요될 수 있습니다.
```bash
docker-compose up -d
```
## 서비스 접속 정보
| 서비스 | 호스트 포트 | 컨테이너 포트 | 주소 |
|---|---|---|---|
| HTTPS | `4430` | `443` | `https://gitlab.geumdo.net:4430` |
| HTTP | `8081` | `80` | `http://gitlab.geumdo.net:8081` (HTTPS로 자동 리다이렉트) |
| SSH | `2224` | `22` | (Git 클라이언트가 사용) |
### 초기 관리자 비밀번호 확인
GitLab이 처음 실행되면 초기 관리자(`root`) 계정의 비밀번호가 자동으로 생성됩니다. 아래 명령어로 확인할 수 있습니다.
```bash
# 컨테이너가 완전히 실행된 후 (몇 분 소요)
docker exec -it gitlab-web-1 grep 'Password:' /etc/gitlab/initial_root_password
```
확인된 비밀번호를 사용하여 웹 인터페이스에 `root` 계정으로 로그인한 후 즉시 변경하는 것을 권장합니다.
\ No newline at end of file
version: '3'
services:
web:
image: 'gitlab/gitlab-ce'
restart: always
hostname: 'gitlab.geumdo.net'
environment:
GITLAB_OMNIBUS_CONFIG: |
external_url 'https://gitlab.geumdo.net'
nginx['redirect_http_to_https'] = true
nginx['ssl_certificate'] = "/etc/gitlab/ssl/fullchain.pem"
nginx['ssl_certificate_key'] = "/etc/gitlab/ssl/privkey.pem"
nginx['ssl_dhparam'] = "/etc/gitlab/ssl/dhparams.pem"
gitlab_rails['gitlab_shell_ssh_port'] = 2224
ports:
- '8081:80'
- '4430:443'
- '2224:22'
volumes:
- '${GITLAB_HOME}/config:/etc/gitlab'
- '${GITLAB_HOME}/logs:/var/log/gitlab'
- '${GITLAB_HOME}/data:/var/opt/gitlab'
shm_size: '256m'
# os with ssh
FROM ubuntu:20.04
# package procedure(update&upgrade&install)
RUN apt-get update && \
apt-get upgrade -y
RUN apt-get install -y openssh-server
RUN apt-get install -y mariadb-server mariadb-client
RUN apt-get install -y vim net-tools apt-utils iputils-ping wget tar curl language-pack-ko openjdk-8-jdk maven
#package clean unused
RUN apt-get clean && \
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
# Set up configuration for SSH
RUN mkdir /var/run/sshd
RUN echo 'root:!@#gds$%^' | chpasswd
RUN sed -ri 's/^#?PermitRootLogin\s+.*/PermitRootLogin yes/' /etc/ssh/sshd_config
RUN echo " StrictHostKeyChecking no" >> /etc/ssh/ssh_config
# SSH login fix. Otherwise, user is kicked off after login
RUN sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/sshd
ENV NOTVISIBLE "in users profile"
RUN echo "export VISIBLE=now" >> /etc/profile
# SET LOCALE
RUN echo "LANG=ko_KR.UTF-8" >> /etc/default/locale && \
echo "LC_MESSAGES=ko_KR.UTF-8" >> /etc/default/locale
# SET DB
RUN sed -ri 's/^#?bind-address\s+.*/bind-address = 0.0.0.0/' /etc/mysql/mariadb.conf.d/50-server.cnf
RUN echo "default-character-set = utf8mb4" >> /etc/mysql/mariadb.conf.d/50-server.cnf
RUN echo "lower_case_table_names = 1" >> /etc/mysql/mariadb.conf.d/50-server.cnf
RUN echo "default-time-zone = '+9:00'" >> /etc/mysql/mariadb.conf.d/50-server.cnf
# wget tomcat8.5.latest(tomcat 사양에 따라 dist 변경 필요)
RUN wget https://archive.apache.org/dist/tomcat/tomcat-8/v8.5.98/bin/apache-tomcat-8.5.98.tar.gz
RUN tar -xf apache-tomcat-8.5.98.tar.gz -C /usr/local
RUN rm apache-tomcat-8.5.98.tar.gz
RUN mv /usr/local/apache-tomcat-8.5.98 /usr/local/tomcat
# java and tomcat path
RUN export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64 >> /etc/profile
RUN export CATALINA_HOME=/usr/local/tomcat >> /etc/profile
RUN export CLASSPATH=.:$JAVA_HOME/jre/lib/ext:$JAVA_HOME/lib/tools.jar:$CATALINA_HOME/lib/jsp-api.jar:$CATALINA_HOME/lib/servlet-api.jar >> /etc/profile
RUN export LANG=ko_KR.UTF-8 >> /etc/profile
RUN bash -c 'source /etc/profile'
#run script folder and copy script
RUN mkdir /service_script
COPY start_service.sh /service_script
COPY setting.sql /service_script
RUN chmod +x /service_script/start_service.sh
# Expose port
EXPOSE 22 443 3306 8080
# Run SSH,DB,TOMCAT,SVN
CMD ["/service_script/start_service.sh"]
# Java / Tomcat / MariaDB Docker 환경
이 프로젝트는 Java 웹 애플리케이션을 위한 완전한 Docker 환경을 제공합니다. Ubuntu 20.04를 기반으로 OpenJDK 8, Tomcat 8.5, MariaDB 서버 및 SSH 서버를 포함하고 있습니다.
## 주요 기능
- **베이스 이미지**: Ubuntu 20.04
- **Java**: OpenJDK 8, Maven
- **웹 애플리케이션 서버(WAS)**: Apache Tomcat 8.5.98
- **데이터베이스**: MariaDB Server
- **원격 접속**: OpenSSH Server
## 사전 요구사항
- [Docker](https://www.docker.com/get-started)
- [Docker Compose](https://docs.docker.com/compose/install/)
## 사용 방법
제공되는 쉘 스크립트를 사용하여 Docker 볼륨 생성, 이미지 빌드, 서비스 시작을 한 번에 처리할 수 있습니다.
### 1. 서비스 시작 및 빌드
아래 명령어를 실행하여 Docker 컨테이너를 빌드하고 백그라운드에서 실행합니다.
```bash
./rebuild_docker.sh
```
이 스크립트는 다음 작업을 자동으로 수행합니다:
1. 데이터베이스, WAS 설정 등을 저장하기 위한 Docker 볼륨(`dbdata`, `dbconfig`, `wasconfig`, `data`, `wardata`)을 확인하고 없는 경우 생성합니다.
2. `Dockerfile`을 기반으로 이미지를 빌드합니다.
3. `docker-compose.yml` 설정을 사용하여 서비스를 시작합니다.
### 2. 서비스 중지
실행 중인 서비스를 중지하려면 아래 명령어를 사용합니다.
```bash
docker-compose down
```
## 서비스 접속 정보
| 서비스 | 호스트 포트 | 컨테이너 포트 | 주소 / 명령어 | 계정 | 비밀번호 |
|---|---|---|---|---|---|
| SSH | `2233` | `22` | `ssh root@<서버_IP> -p 2233` | `root` | `!@#gds$%^` |
| Tomcat (HTTP) | `8092` | `8080` | `http://<서버_IP>:8092` | - | - |
| Tomcat (HTTPS)| `4446` | `443` | `https://<서버_IP>:4446` | - | - |
| MariaDB | `33064`| `3306` | `<서버_IP>` | `root` | `fnxmdkagh` |
## 데이터 영속성 및 설정
이 환경은 Docker 볼륨 및 바인드 마운트를 사용하여 데이터와 설정을 컨테이너 외부 호스트에 영속적으로 저장합니다.
- **볼륨**:
- `dbdata`: MariaDB 데이터 파일 (`/var/lib/mysql`)
- `dbconfig`: MariaDB 설정 파일 (`/etc/mysql`)
- `wasconfig`: Tomcat 설정 파일 (`/usr/local/tomcat/conf`)
- `wardata`: Tomcat 웹 애플리케이션 (`/usr/local/tomcat/webapps`)
- `data`: 범용 데이터 저장용 (`/data`)
- **바인드 마운트**:
- `./ssl/`: SSL 인증서를 저장하는 로컬 디렉토리입니다. 이 폴더에 있는 파일들은 컨테이너의 `/usr/local/tomcat/ssl` 경로에 마운트됩니다. HTTPS를 사용하려면 이곳에 인증서와 키 파일을 위치시켜야 합니다.
\ No newline at end of file
version: '3'
services:
os:
build:
context: .
dockerfile: Dockerfile
container_name: docker_java
restart: always
ports:
- "2233:22" # SSH
- "8092:8080" # tomcat
- "4446:443" # https
- "33064:3306" #mariadb
network_mode: bridge
volumes:
- dbdata:/var/lib/mysql
- dbconfig:/etc/mysql
- wasconfig:/usr/local/tomcat/conf
- data:/data #java팀 전용
- wardata:/usr/local/tomcat/webapps #default tomcat 경로 사용시
- ./ssl/:/usr/local/tomcat/ssl #ssl 파일경로
volumes:
dbdata:
external: true
dbconfig:
external: true
wasconfig:
external: true
data:
external: true
wardata:
external: true
#!/bin/sh
# Check and create volumes if they don't exist
create_volume() {
docker volume inspect $1 > /dev/null 2>&1
if [ $? -eq 0 ]; then
echo "Volume '$1' already exists."
else
docker volume create --name=$1
echo "Volume '$1' created."
fi
}
create_volume svndata
create_volume dbdata
create_volume dbconfig
create_volume wasconfig
create_volume data
create_volume wardata
# Build Docker image with explicit build context and Dockerfile path
docker build -t docker_java .
# Run Docker Compose with a specific container name
docker-compose up -d
#원하는 루트 원격 계정 password 입력
grant all privileges on *.* to root@'%' identified by 'fnxmdkagh';
flush privileges;
-----BEGIN CERTIFICATE-----
MIIEszCCA5ugAwIBAgIQCyWUIs7ZgSoVoE6ZUooO+jANBgkqhkiG9w0BAQsFADBh
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBH
MjAeFw0xNzExMDIxMjI0MzNaFw0yNzExMDIxMjI0MzNaMGAxCzAJBgNVBAYTAlVT
MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
b20xHzAdBgNVBAMTFlJhcGlkU1NMIFRMUyBSU0EgQ0EgRzEwggEiMA0GCSqGSIb3
DQEBAQUAA4IBDwAwggEKAoIBAQC/uVklRBI1FuJdUEkFCuDL/I3aJQiaZ6aibRHj
ap/ap9zy1aYNrphe7YcaNwMoPsZvXDR+hNJOo9gbgOYVTPq8gXc84I75YKOHiVA4
NrJJQZ6p2sJQyqx60HkEIjzIN+1LQLfXTlpuznToOa1hyTD0yyitFyOYwURM+/CI
8FNFMpBhw22hpeAQkOOLmsqT5QZJYeik7qlvn8gfD+XdDnk3kkuuu0eG+vuyrSGr
5uX5LRhFWlv1zFQDch/EKmd163m6z/ycx/qLa9zyvILc7cQpb+k7TLra9WE17YPS
n9ANjG+ECo9PDW3N9lwhKQCNvw1gGoguyCQu7HE7BnW8eSSFAgMBAAGjggFmMIIB
YjAdBgNVHQ4EFgQUDNtsgkkPSmcKuBTuesRIUojrVjgwHwYDVR0jBBgwFoAUTiJU
IBiV5uNu5g/6+rkS7QYXjzkwDgYDVR0PAQH/BAQDAgGGMB0GA1UdJQQWMBQGCCsG
AQUFBwMBBggrBgEFBQcDAjASBgNVHRMBAf8ECDAGAQH/AgEAMDQGCCsGAQUFBwEB
BCgwJjAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMEIGA1Ud
HwQ7MDkwN6A1oDOGMWh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEds
b2JhbFJvb3RHMi5jcmwwYwYDVR0gBFwwWjA3BglghkgBhv1sAQEwKjAoBggrBgEF
BQcCARYcaHR0cHM6Ly93d3cuZGlnaWNlcnQuY29tL0NQUzALBglghkgBhv1sAQIw
CAYGZ4EMAQIBMAgGBmeBDAECAjANBgkqhkiG9w0BAQsFAAOCAQEAGUSlOb4K3Wtm
SlbmE50UYBHXM0SKXPqHMzk6XQUpCheF/4qU8aOhajsyRQFDV1ih/uPIg7YHRtFi
CTq4G+zb43X1T77nJgSOI9pq/TqCwtukZ7u9VLL3JAq3Wdy2moKLvvC8tVmRzkAe
0xQCkRKIjbBG80MSyDX/R4uYgj6ZiNT/Zg6GI6RofgqgpDdssLc0XIRQEotxIZcK
zP3pGJ9FCbMHmMLLyuBd+uCWvVcF2ogYAawufChS/PT61D9rqzPRS5I2uqa3tmIT
44JhJgWhBnFMb7AGQkvNq9KNS9dd3GWc17H/dXa1enoxzWjE0hBdFjxPhUb0W3wi
8o34/m8Fxw==
-----END CERTIFICATE-----
\ No newline at end of file
-----BEGIN CERTIFICATE-----
MIIDjjCCAnagAwIBAgIQAzrx5qcRqaC7KGSxHQn65TANBgkqhkiG9w0BAQsFADBh
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBH
MjAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGExCzAJBgNVBAYTAlVT
MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcyMIIBIjANBgkqhkiG
9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzfNNNx7a8myaJCtSnX/RrohCgiN9RlUyfuI
2/Ou8jqJkTx65qsGGmvPrC3oXgkkRLpimn7Wo6h+4FR1IAWsULecYxpsMNzaHxmx
1x7e/dfgy5SDN67sH0NO3Xss0r0upS/kqbitOtSZpLYl6ZtrAGCSYP9PIUkY92eQ
q2EGnI/yuum06ZIya7XzV+hdG82MHauVBJVJ8zUtluNJbd134/tJS7SsVQepj5Wz
tCO7TG1F8PapspUwtP1MVYwnSlcUfIKdzXOS0xZKBgyMUNGPHgm+F6HmIcr9g+UQ
vIOlCsRnKPZzFBQ9RnbDhxSJITRNrw9FDKZJobq7nMWxM4MphQIDAQABo0IwQDAP
BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUTiJUIBiV
5uNu5g/6+rkS7QYXjzkwDQYJKoZIhvcNAQELBQADggEBAGBnKJRvDkhj6zHd6mcY
1Yl9PMWLSn/pvtsrF9+wX3N3KjITOYFnQoQj8kVnNeyIv/iPsGEMNKSuIEyExtv4
NeF22d+mQrvHRAiGfzZ0JFrabA0UWTW98kndth/Jsw1HKj2ZL7tcu7XUIOGZX1NG
Fdtom/DzMNU+MeKNhJ7jitralj41E6Vf8PlwUHBHQRFXGU7Aj64GxJUTFy8bJZ91
8rGOmaFvE7FBcf6IKshPECBV1/MUReXgRPTqh5Uykw7+U0b6LJ3/iyK5S9kJRaTe
pLiaWN0bfVKfjllDiIGknibVb63dDcY3fe0Dkhvld1927jyNxF1WW6LZZm6zNTfl
MrY=
-----END CERTIFICATE-----
\ No newline at end of file
-----BEGIN PKCS7-----
MIIOoQYJKoZIhvcNAQcCoIIOkjCCDo4CAQExADALBgkqhkiG9w0BBwGggg50MIIG
JzCCBQ+gAwIBAgIQCM3++k3vx6kzgPcZbFWBITANBgkqhkiG9w0BAQsFADBgMQsw
CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu
ZGlnaWNlcnQuY29tMR8wHQYDVQQDExZSYXBpZFNTTCBUTFMgUlNBIENBIEcxMB4X
DTI0MTEyMDAwMDAwMFoXDTI1MTExOTIzNTk1OVowFjEUMBIGA1UEAxMLZ2JtYXgu
b3Iua3IwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCGGgizvgsuIYcS
0CGxAsWyWCC53ty4byV1JPlJt+Bt61fHy3Wq4jQ+88IkoCGKNa1+4XU8TmAHVUJo
OmzUGtJ7YCNzzSSP5pxkPDwNIwb5CSdc8FkJz1h09rrDsluHPPHFHi3B5pL+7pVh
VvfvXTYWr2zgD5NMi3PEEuSH1cMNvDI304pWH/fvsP/lranDz4KA9aEPc8ZemxXc
9pt00yiZhtrhM05coEM9+euFomt/zb6KJQej1Q5Kn4NQXdXtC9PxLV66FNulaA2G
Xa2Fe+lozwT3kfTVYbRHllDpJkg0X/BpJK6idaQjt4pyerWAA9CI72M8bJC+to0l
U95lNOffAgMBAAGjggMlMIIDITAfBgNVHSMEGDAWgBQM22yCSQ9KZwq4FO56xEhS
iOtWODAdBgNVHQ4EFgQU+BFYxo0yFc9K0AcMF/dkszQ6k5owJwYDVR0RBCAwHoIL
Z2JtYXgub3Iua3KCD3d3dy5nYm1heC5vci5rcjA+BgNVHSAENzA1MDMGBmeBDAEC
ATApMCcGCCsGAQUFBwIBFhtodHRwOi8vd3d3LmRpZ2ljZXJ0LmNvbS9DUFMwDgYD
VR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjA/BgNV
HR8EODA2MDSgMqAwhi5odHRwOi8vY2RwLnJhcGlkc3NsLmNvbS9SYXBpZFNTTFRM
U1JTQUNBRzEuY3JsMHYGCCsGAQUFBwEBBGowaDAmBggrBgEFBQcwAYYaaHR0cDov
L3N0YXR1cy5yYXBpZHNzbC5jb20wPgYIKwYBBQUHMAKGMmh0dHA6Ly9jYWNlcnRz
LnJhcGlkc3NsLmNvbS9SYXBpZFNTTFRMU1JTQUNBRzEuY3J0MAwGA1UdEwEB/wQC
MAAwggF+BgorBgEEAdZ5AgQCBIIBbgSCAWoBaAB3ABLxTjS9U3JMhAYZw48/ehP4
57Vih4icbTAFhOvlhiY6AAABk0hojuMAAAQDAEgwRgIhAMAlpNH6jOBuxy+gOK2r
5ZI4y0ERzWbGlCGTzIu4eqigAiEAmzmjKsEa6DKDk9oru7i2zpHmb1hHGT6DUPNQ
ogGy5MMAdQB9WR4S4XgqexxhZ3xe/fjQh1wUoE6VnrkDL9kOjC55uAAAAZNIaI8b
AAAEAwBGMEQCIFOGoQwDUyYMJsxzbLdgSIGLWr/vCx11iB5hriCVU7mpAiBKH0hO
RMEOoUVJ60PlYj+TKvGAT9jqA3+PoZJTs+sSiAB2AObSMWNAd4zBEEEG13G5zsHS
QPaWhIb7uocyHf0eN45QAAABk0hojycAAAQDAEcwRQIhAOEORNrLq+CeR/Uey87R
/GC2W2dt95qXNkVdWoY5HnfsAiBR1a8RLk2yFrGjh0c1CN8qBm1doi2evYVN9Cn7
bncEIDANBgkqhkiG9w0BAQsFAAOCAQEAEnD5P6N2hB5WeiRymVecA1drkQVcdN1d
CY1spy9sBd6dx3l7VEAJcTkGbDgKrxJzHFx3dAAnLLYa4L9xuEDZwWEguxm06ggc
XnutEQgob0awDS8hiCF85G1HP/WEUr3N7y5aqxYeuIKzcx+ib80LfVtQQVOEvBdg
6SZF4o6uQakRs6tfVbHXa0D5+4qDSremSJAKWSs8o9Aa+QvoPQuWrm3OJ+ltk3R2
5WKF4OSH1h+595xRHlBNPct69UgNVIBYhzzeoz/XipwU/Cx0sNjRc9q05pqDp+V1
OSsQKSxWtkoNMbaXMLgg8C0S+hqshp74JCaPZq5Q5GkCb00HzXzpEDCCBLMwggOb
oAMCAQICEAsllCLO2YEqFaBOmVKKDvowDQYJKoZIhvcNAQELBQAwYTELMAkGA1UE
BhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRpZ2lj
ZXJ0LmNvbTEgMB4GA1UEAxMXRGlnaUNlcnQgR2xvYmFsIFJvb3QgRzIwHhcNMTcx
MTAyMTIyNDMzWhcNMjcxMTAyMTIyNDMzWjBgMQswCQYDVQQGEwJVUzEVMBMGA1UE
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
tqEAMQA=
-----END PKCS7-----
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment