Jupyter Notebook를 사용함으로써 ssh 접속을 통하지 않고도 바로 웹 브라우저에서 ec2 서버를 관리할 수 있다는 장점이 있어 사용한다.
$ sudo apt-get install python3-pip
$ sudo pip3 install notebook
#python3 실행
$ python3
>> from notebook.auth import pwd
>> pwd()
# verify password 복사
$ jupyter notebook --generate-config
# 주피터 노트북 환경설정 파일 생성 후 나오는 루트 복사
$ sudo vi #복사한 경로
# 파일 마지막 부분에 붙여넣기 할 내용
c = get_config()
c.NotebookApp.password = u'복사한 verify password'
c.NotebookApp.ip = 'EC2 Private IPv4'
c.NotebookApp.notebook_dir = '/'
$ cd /home/ubuntu/.jupyter && jupyter notebook --config jupyter_notebook_config.py # jupyter notebook (8888번 포트) 실행
→ {public IPv4 주소}:8888
로 접속 가능
# 백그라운드에서도 항상 실행 가능한 상태로 만들기
$ bg
$ disown -h
보안 적용 이전 열어주었던 8888번 포트를 일단 닫아주기 위해 아래 명령어를 이용하자.
$ sudo netstat -nap | grep 8888
$ sudo kill -9 {포트가 실행중인 PID}
$ mkdir ssl
$ cd ssl
$ sudo openssl req -x509 -nodes -days 365 -newkey rsa:1024 -keyout "cert.key" -out "cert.pem" -batch
or
$ openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout mykey.key -out mycert.pem
-----BEGIN PRIVATE KEY-----
-----END PRIVATE KEY-----
-----BEGIN PUBLIC KEY-----
-----END PUBLIC KEY-----
# Jupyter Notebook config 파일에 아래 내용 추가
c.NotebookApp.certfile = u'/home/ubuntu/ssl/cert.pem'
c.NotebookApp.keyfile = u'/home/ubuntu/ssl/cert.key'
Openssl로 SSL 을 위한 인증서 발급하기 (HTTPS)
**$ openssl req -new -key private.key -out private.csr**
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:KR
State or Province Name (full name) [Some-State]:Seoul
Locality Name (eg, city) []:Yongsan-gu
Organization Name (eg, company) [Internet Widgits Pty Ltd]:simya
Organizational Unit Name (eg, section) []:Server
Common Name (e.g. server FQDN or YOUR name) []:www.simya.com
Email Address []:jun20020216@gmail.com
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:test
An optional company name []:test
-----BEGIN CERTIFICATE REQUEST-----
-----END CERTIFICATE REQUEST-----
$ openssl req -x509 -days 365 -key {private.key} -in {private.csr} -out {mycommoncrt.crt} -days 365
-----BEGIN CERTIFICATE-----
-----END CERTIFICATE-----
서버 접속 이외에도 주피터 노트북을 통해 ec2에 접근할 수 있도록 Jupyter Notebook 자체를 시스템으로 등록해준다.
$ sudo vi /etc/systemd/system/jupyter.service
아래 내용으로 파일을 추가해준다.
[Unit]
Description=Jupyter Notebook Server
[Service]
Type=simple
User=ubuntu
ExecStart = /usr/bin/sudo /usr/local/bin/jupyter-notebook --allow-root --config=/home/ubuntu/.jupyter/jupyter_notebook_config.py
[Install]
WantedBy=multi-user.target
~
~
~
$ sudo systemctl daemon-reload
$ sudo systemctl enable jupyter
Created symlink /etc/systemd/system/multi-user.target.wants/jupyter.service → /etc/systemd/system/jupyter.service.
$ sudo systemctl start jupyter
$ sudo systemctl status jupyter
● jupyter.service - Jupyter Notebook Server
Loaded: loaded (/etc/systemd/system/jupyter.service; enabled; vendor preset: enabled)
Active: active (running) since Mon 2023-01-30 15:29:24 UTC; 4s ago
Main PID: 5345 (sudo)
Tasks: 2 (limit: 1143)
Memory: 48.1M
CPU: 628ms
CGroup: /system.slice/jupyter.service
├─5345 /usr/bin/sudo /usr/local/bin/jupyter-notebook --allow-root --config=/home/ubuntu/.jupyter/jupyter_n>
└─5346 /usr/bin/python3 /usr/local/bin/jupyter-notebook --allow-root --config=/home/ubuntu/.jupyter/jupyte>
https://{Public IPv4 주소}:8888로 접속 시 아래와 같이 터미널을 실행시킬 수 있다.
Docker를 다운받기 위한 기본 환경을 셋팅해준다.
$ sudo apt update
$ sudo apt install apt-transport-https ca-certificates software-properties-common
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg |sudo apt-key add -
$ apt-cache policy docker-ce
$ sudo apt install docker-ce
Docker는 설치와 동시에 시스템 서비스로 자동 등록 되어 sudo systemctl status docker
로 status를 확인해보면 정상적으로 구동중임을 알 수 있다.
Docker 이미지에 올릴 서버의 종류, 개발자 정보, 자동으로 실행할 명령어 등을 작성해준다.
### Container 정보
FROM ubuntu:22.04
MAINTAINER yejunpark1 <jun20020216@gmail.com>
### 수행할 명령
RUN apt-get update
RUN apt-get install -y apache2
#install Apache web server (Only 'yes') -> 선택 옵션에 미리 응답
# Open HTTP Port
EXPOSE 80
### 명령 종료 후에도 항상 구동 중인 상태로 설정할 명령어
CMD ["apachectl", "-D", "FOREGROUND"]
아파치의 경우, 특정 컨테이너의 특정 명령을 수행한 이후에도 계속 구동된 상태로 유지되어야 하므로 CMD로 설정해준다.
$ docker build -t example . #Docker 이미지 build 하기 (하나의 서버로서 Dockerfile에 지정해준 명령어를 모두 수행한다.)
$ docker images #빌드된 내용 확인하기
$ docker run -p {내 서버의 포트}:{도커 컨테이너의 포트}
**{IP주소}/{Domain}:포트번호
** 에서 포트 번호에 해당하는 건 내 서버의 포트 이다! 80:80으로 80번(http) 포트에 접속해주면 아래와 같은 아파치 서버의 화면이 구동됨을 알 수 있다. $ docker rm -f `docker ps -a -q` # Docker Container 모두 종료 및 삭제
Docker를 활용하여 APM(Apache-Php-Mysql)를 구축하기 위해 테스트로 작성했던 /home/ubuntu/example 경로에 저장된 Dockerfile을 수정해준다.
FROM ubuntu:22.04
MAINTAINER yejunpark1 <jun20020216@gmail.com>
# Avoding user interaction with tzdata
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update
RUN apt-get install -y apache2 #install Apache web server (Only 'yes')
RUN apt-get install -y software-properties-common
RUN add-apt-repository ppa:ondrej/php
RUN apt-get update
RUN apt-get install -y php5.6
# Open HTTP Port
EXPOSE 80
CMD ["apachectl", "-D", "FOREGROUND"]
특정 명령어의 경우, 선택 옵션을 응답받아야 하는 것들이 있다. 하지만 이들은 Docker의 이미지로 다운을 받기에 당장 응답이 불가능하다.
이는 ENV DEBIAN_FRONTEND=noninteractive
로 오류를 해결할 수 있다. 사용자의 응답을 일단 넘어간다는 의미인데, 이는 으로 이미지가 설치되므로 그냥 삭제해주자.
$ docker run -p 80:80 -v /home/ubuntu/example/html:/var/www/html example
php의 기본 경로인 /var/www/html을 띄워준다. 우분투 서버에 존재하는 파일을 연결시켜주기 위해 html 파일을 아래 내용으로 작성한 후, 다시 80번 포트로 접속하면 php 페이지가 뜨는 것을 확인할 수 있다.
<?php phpinfo(); ?>
# Docker 이미지 다운로드
$ docker run -d -p 9876:3306 -e MYSQL_ROOT_PASSWORD=password mysql:5.6
# 서버에도 MySQL 설치
$ sudo apt install mysql-client-core-5.7
$ sudo apt install mariadb-client-core-10.1
DockerHub에 존재하는 이미지를 run으로 실행하면 즉시 다운로드되며, 필요한 환경변수들을 넘겨주어 실행이 가능하다.
Bash 명령어로 MySQL 컨테이너에 접속할 수 있도록 아래 명령어를 실행한다.
$ docker exec -it f676e158713f /bin/bash # 실제로 해당 컨테이너에 접속한 것과 같은 효과를 낼 수 있다.
$ docker inspect {Container ID} # 접속 가능한 IP 주소를 찾아 MySQL에 접속한다.
$ mysql -u root -p --host {IP주소} --port 3306
Docker Container는 언제든 사라지고 실행될 수 있으므로, 영구적으로 데이터를 보존해야 하는 MySQL은 일시적인 Container로 관리하지 않는다. 일반적으로는 이를 통해 MySQL을 구축하기 보다 AWS RDS와 같은 데이터베이스를 이용한다.
MySQL에 접속하여 유저와 데이터베이스를 만들어본 후, 포트는 9876번, IP는 EC2 공인IP, 생성한 유저와 비밀번호를 이용해 외부 접속 테스트를 해보면 잘 접속된 것을 확인할 수 있다.
*Docker Login 방법
$ docker login
username: {dockerhub 사용자명}
password: {dockerhub 비밀번호}
Authenticating with existing credentials...
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
Login Succeeded
여기서 password 부분에 dockerhub의 비밀번호를 그대로 입력하면 위와 같은 내용이 뜬다. 이외에도 로그인하는 방법이 한 가지 더 있는데, https://hub.docker.com/ 에 접속하여 [Account Settings] > [Security] > [New Access Token] 후 이 토큰을 비밀번호로 입력하면 된다. 이를 보안상 더 권장하는 것 같다.
$ docker login -u {username}
password: {Access Token}
Dockerfile 수정 - 아래 패키지 설치 명령을 추가해준다.
# Connect PHP & MySQL
RUN apt-get install -y php5.6-mysql
$ docker build -t example .
$ docker run -p 80:80 -v /home/ubuntu/example/html:/var/www/html example
index.php 파일을 아래 내용과 같이 php 문법을 이용하여 수정해준다. 이와 같이 내용이 많은 파일에 접근할 때, Jupyter Notebook을 사용하면 GUI로 수정이 가능하여 좀 더 편리하게 접근할 수 있다.
<?php
$conn = mysqli_connect(
'{EC2 Public IP주소}',
'{usernmae}',
'{password}',
'{데이터베이스명}',
'{포트번호}'
);
if (mysqli_connect_errno()) {
echo "Failed to connect to MySQL: ".mysqli_connect_error();
}
$sql = "SELECT VERSION()";
$result = mysqli_query($conn, $sql);
$row = mysqli_fetch_array($result);
print_r($row["VERSION()"]);
?>
다시 http://{퍼블릭 IP}/ 리로딩했을 때, 버전이 뜨면 성공적으로 실행된 것이다.
RDS 인스턴스를 생성한다. 여기서 생성한 DB명, 사용자이름, 비밀번호 등을 잘 기록해두자.
이를 바탕으로 이전에 작성했던 index.php 파일의 내용을 수정해줄 것이다.
$conn = mysqli_connect(
'{RDS 엔드포인트}',
'{usernmae}',
'{password}',
'{데이터베이스명}',
'{포트번호}'
);
Dockerfile과 프로젝트의 소스코드를 같은 루트에 두는 것이 일반적이다
깃헙에 올라와있는 Dockerfile을 읽어 DockerHub에서 자동으로 빌드를 수행해주는 강력한 기능이 있다. 깃헙에 업로드만 해도 자동으로 빌드가 이루어지므로 자동화 되어 관리할 수 있는 것이다.
cd /home
git clone https://github.com/jun02160/docker-test
cd docker-test
# Login For Private Docker Repository
docker login
docker pull yejunpark1/docker-practice
docker run -p 80:80 -v /home/docker-test/Project:/var/www/html yejunpark1/docker-practice
Jenkins를 사용하면 배포 자동화가 가능해진다. 소스코드를 push 하는 것만으로 도커에 자동적으로 pull 되어 빌드시킬 수 있었는데, 이를 조금 더 간편하게 해주는 툴이 바로 Jenkins이다.
Docker에서 Jenkins 이미지를 pull 받고 실행시킨다.
https://hub.docker.com/r/jenkins/jenkins → 이전과 바뀐 방식으로 공식 DockerHub 문서 참고하기
$ docker pull jenkins/jenkins:lts-jdk11
$ docker run -d -p 8080:8080 -p 50000:50000 --restart=on-failure -v /jenkins_home:/var/jenkins_home -v /var/run/docker.sock:/var/run/docker.sock --name jenkins -u root jenkins/jenkins:lts-jdk11
$ docker exec -it jenkins cat /var/jenkins_home/secrets/initialAdminPassword # jenkins 패스워드 조회
/var/jenkins_home
이라는 디렉토리를 /jenkins와 마운트하여 데이터를 보존할 수 있다.*참고 자료 - https://hudi.blog/install-jenkins-with-docker-on-ec2/
docker-compose를 이용하여 위와 같은 복잡한 명령 없이 간편하게 도커 컨테이너를 실행할 수 있다.
version: "3"
services:
jenkins:
image: jenkins/jenkins:lts
user: root
volumes:
- ./jenkins:/var/jenkins_home
ports:
- 8080:8080
$ sudo docker-compose up -d # 컨테이너를 데몬으로 실행시킨다.
## Docker 서비스 데몬 폴더 생성
$ sudo mkdir -p /etc/systemd/system/docker.service.d
## 프록시 서버 설정파일 생성
$ sudo vi /etc/systemd/system/docker.service.d/http-proxy.conf
## http-proxy.conf 파일 내용 작성
[Service]
Environment="HTTP_PROXY=http://proxy.example.com:80"
Environment="HTTPS_PROXY=https://proxy.example.com:443"
Environment="NO_PROXY=localhost,127.0.0.1,docker-registry.example.com,.corp"
## Docker 데몬 재시작
$ sudo systemctl daemon-reload
$ sudo systemctl restart docker
## 적용 결과 확인
$ sudo systemctl show --property=Environment docker
*참고 자료 - https://kim-dragon.tistory.com/255
프록시 파일 작성 시 가능한 NO_PROXY 옵션
1.2.3.4
)*
)foo.example.com
및 example.com
:[example.com](http://example.com)
일치 example.com
및foo.example.com
, 및 .example.com
만 일치foo.example.com
*
)는 프록싱을 수행하지 않아야 함을 나타냅니다.1.2.3.4:80 foo.example.com:80
) 및 도메인 이름(foo.example.com:80
) 에서 허용됩니다.**만약 docker login 시 아래와 같은 에러가 발생한다면?
Error response from daemon: Get "https://registry-1.docker.io/v2/": proxyconnect tcp: dial tcp: lookup proxy.example.com: no such host
/etc/resolv.conf 파일 내용을 수정하여 DNS를 8.8.8.8로 변경해주자!
$ sudo vi /etc/resolv.conf # 아래 내용 추가
$ isudo vi /etc/resolv.conf
nameserver 8.8.8.8
nameserver 8.8.4.4
## Docker 데몬 재시작
$ sudo systemctl daemon-reload
$ sudo systemctl restart docker
127.0.0.53 → 8.8.8.8
*jenkins 실행 시 Public IP주소로 접속이 안된다면 프록시 설정을 바꾸어주면 된다.
$ sudo vi /etc/docker/daemon.json
{ "insecure-registries" :
["myregistrydomain.com:5000"]
}
이후, {public IPv4 주소}:8080
으로 접속하여 jenkins 로그인을 해준다.
$ docker logs {Container ID} # 여기서 뜨는 비밀번호를 입력하여 로그인할 수 있다.
→ Install suggested plugins (기본 플러그인 설치 항목 선택)
Docker 안에 Docker가 존재하는 DinD 방식을 사용할 것이므로 jenkins에 따로 Docker를 설치해줘야 한다. 이는 배포 자동화 시 Docker 프로젝트를 가져오고 실행시키는 과정에서 docker 명령어를 사용하기 위해 다운받아야 하는 것이다.
$ docker exec -it {Container ID} /bin/bash
$ curl -fsSLO https://get.docker.com/builds/Linux/x86_64/docker-17.04.0-ce.tgz # Jenkins 내부에 docker 설치 - 압축파일 다운로드
$ tar xzvf docker-17.04.0-ce.tgz
$ mv docker/docker /usr/local/bin # docker 명령어를 실행시킬 수 있도록 실행파일을 옮겨준다.
$ rm -r docker docer-17.04.0-ce.tgz # 용량을 줄이기 위해 기존 압축파일은 삭제
$ docker login # private repositor에 접근하기 위함
🐳 Jenkins를 사용하여 Docker project를 가져오고 자동으로 빌드, 즉 배포가 되도록 해준다.
Jenkins의 Execute shell에 빌드 시 자동 실행될 수 있는 명령어를 추가해준다.
cd backend
git pull
docker pull {사용자명}/{도커이미지명}
docker run -p 80:80 -v backend
그 다음, 빌드 유발에서 [빌드를 원격으로 유발]에 체크해주고 보안을 위해 Authentication Token을 어려운 문자열로 설정해준다. → 아래 원격 빌드를 위한 주소가 아래와 같이 뜨게된다. 이 주소로 접속만 해도 바로 빌드가 실행되어 더욱 편리하게 자동화가 되도록 하는 도구임을 알 수 있다.
JENKINS_URL
/job/{jenkins item명}
/build?token=TOKEN_NAME
or /buildWithParameters?token=TOKEN_NAME
이후는 github 로그인 정보를 jenkins 컨테이너 내부에 기록하기 위한 과정이다.
$ docker exec -it {Container ID} /bin/bash
$ cd {github 프로젝트명}
$ git config --global credential.helper "cache --timeout 7200" # 깃헙 계정정보를 젠킨스 컨테이너 내부에서 그대로 보여지도록 노출시키는 건 보안상으로 취약하므로, 이를 주기적으로 갱신시키도록 타이머를 설정해줘야 한다. (여기서는 7200s = 2시간으로 설정)
## 또는 GitHub의 Access Token을 발급받아서 이를 직접 등록시켜주는 방식도 있다. -> 이 방식이 다른 개발자들에게 노출되지 않고 관리할 수 있어 조금 더 권장된다.
*Github personal token으로 인증하는 방법
GitHub Settings > Developer Setting > Personal Access Token
접근 범위를 아래와 같이 설정한 후에 토큰 생성 (반드시 저장해두기! 한 번만 볼 수 있음)
Jenkins > Manage Jenkins > System Configure > [시스템 설정]
+ADD
클릭하여 Credential 생성하기
Test Connection 시, Credentials verified for user의 내용이 뜨면 성공!
*참고 자료 - https://bcho.tistory.com/1237
동빈나 YouTube 강의를 학습하며 기록한 내용입니다.