Centos7 도커 설치
1. 필요한 패키지 설치
[root@victim ~]# yum -y install yum-utils device-mapper-persistent-data lvm2
2. Docker CE 저장소 추가
[root@victim ~]# yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
3. Docker CE 설치
CentOS 7에서는 Docker CE 를 설치한다.
[root@victim ~]# vi /etc/yum.repos.d/CentOS-Vault.repo
# C7.9.2009
[C7.9.2009-base]
name=CentOS-7.9.2009 - Base
baseurl=http://vault.centos.org/7.9.2009/os/$basearch/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7
enabled=1
[C7.9.2009-updates]
name=CentOS-7.9.2009 - Updates
baseurl=http://vault.centos.org/7.9.2009/updates/$basearch/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7
enabled=1
[C7.9.2009-extras]
name=CentOS-7.9.2009 - Extras
baseurl=http://vault.centos.org/7.9.2009/extras/$basearch/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7
enabled=1
[C7.9.2009-centosplus]
name=CentOS-7.9.2009 - CentOSPlus
baseurl=http://vault.centos.org/7.9.2009/centosplus/$basearch/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7
enabled=1
[C7.9.2009-fasttrack]
name=CentOS-7.9.2009 - Fasttrack
baseurl=http://vault.centos.org/7.9.2009/fasttrack/$basearch/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7
enabled=1
패키지 설치
[root@victim ~]# yum -y install docker-ce docker-ce-cli containerd.io
[root@victim ~]# systemctl enable --now docker.service
[root@victim ~]# systemctl status docker.service
패키지 설명
. docker-ce
- 도커 컨테이너를 빌드하고 실행하는 데 사용되는 기본 기술을 제공 (dockerd).
. docker-ce-cli
- 명령 줄 인터페이스 (CLI) 클라이언트 도커 도구 (docker) 제공
. containerd.io
- 컨테이너 런타임 (runc)을 제공
외부에서 패킷을 받으면 자신이 받는게 아니고 컨네이너로 넘겨줘야 하므로 nat 테이블에 도커룰이 설정되어 있다.
[root@victim ~]# iptables -t nat -nL | grep -i Docker
도커 컨테이너 생성하기
docker 사이트에서 hello-world 이미지를 가져오고 컨테이너를 자동으로 생성한다.
[root@victim ~]# docker run hello-world
도커 이미지를 확인한다.
[root@victim ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest e2ac70e7319a 5 weeks ago 10.1kB
도커 컨테이너를 확인한다.
필드 설명
. CONTAINER ID
- 컨테이너의 고유 ID(짧은 해시로 출력, 전체 해시의 앞 12자리만 표시됨)
. IMAGE
- 컨테이너가 생성될 때 사용한 도커 이미지 이름
. COMMAND
- 컨테이너가 시작될 때 실행된 명령어
. CREATED
- 컨테이너가 만들어진 시간 (e.g.: 2 minutes ago, 5 days ago)
. STATUS
- 컨테이너의 현재 상태
. PORTS
- 컨테이너가 호스트와 연결한 포트 정보
. NAMES
- 도커가 자동 생성한 컨테이너 이름
- 사용자가 컨테이너 이름을 설정하려면 --name 옵션을 사용한다.
[root@victim ~]# docker ps -a
방금 생성한 컨테이너를 삭제한다.
. docker rm 명령어를 사용한다.
. CONTAINER ID, NAMES 로 삭제할 수 있고 값은 모두 다르다.
[root@victim ~]# docker rm 0f0
도커 컨테이너를 삭제한다.
. docker rmi <image name>:<tag name>
[root@victim ~]# docker rmi hello-world:latest
[root@victim ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
도커로 오라클 설치하기
1. Oracle 11g 설치
[root@victim ~]# docker run -d --restart=always -p 1522:1521 \
--name oracle11gxe oracleinanutshell/oracle-xe-11g
2. Oracle 11g XE 접속
[root@victim ~]# docker exec -it oracle11gxe /bin/bash
root@899b1147e996:/# sqlplus system/oracle // sqlplus sys/oracle as sysdba
3. 애플리케이션 접속
SQLDeveloper 접속 설정
Oracle sqldeveloper / DBever 를 사용해서 DBMS에 접속한다.
이때 터널링 설정을 하지 않았기 때문에 Host를 192.168.100.10로 접속한다.
왼쪽 위에 + 버튼을 클릭해서 접속 설정을 저장하고 sys 사용자로 접속한다.
접속 설정
. 윈도우 관리자용 접속 설정
- DockerLinuxOracle11g_sys
NAME: DockerLinuxOracle11g_sys
사용자 이름: sys
롤: SYSDBA
비밀번호: oracle
비밀번호 저장: 체크
호스트 이름: 192.168.100.10
포트: 1522
SID: xe
scott 사용자를 등록한다.
왼쪽 위에 + 버튼을 클릭해서 접속 설정을 저장한다.
접속 설정
. 윈도우 관리자용 접속 설정
- DockerLinuxOracle11g_scott
NAME: DockerLinuxOracle11g_scott
사용자 이름: scott
롤: 기본값
비밀번호: tiger
비밀번호 저장: 체크
호스트 이름: 192.168.100.10
포트: 1522
SID: xe
SSH 터널링을 이용한 Docker 의 Oracle DBMS 접속하기
1. 터널링의 기본 개념
Host OS에서 Oracle 서버 접속하기
. SQLDeveloper 이용해서 접속한다.
- Host OS에서 SQLDeveloper로 접속할 수 있도록 터널링을 설정한다.
- 터널링 설정 전의 접속방법
- [Host OS] 5000 -------------- 1521 [CentOS 7] ------ 1522 [Docker Oracle]
.1 192.168.100.0/24 .10
- 터널링 설정 후의 접속방법
- [Host OS] 1522 -------------- [CentOS 7] ------ 1522 [Docker Oracle]
- 1522/tcp 포트를 오픈하는 이유는 이미 1521/tcp 가 사용중이기 때문이다.
docker inspect: 컨테이너/이미지/볼륨/네트워크의 상세 정보 확인하는 명령어
[root@victim ~]# docker inspect oracle11gxe | grep IPAddress
"SecondaryIPAddresses": null,
"IPAddress": "172.17.0.2",
=> "IPAddress": "172.17.0.2",
도커에서 IP주소는 고정 IP주소가 아니다
2. ssh 터널링 접속 설정
linuxadmin 사용자에서 터널링으로 접속할 사용자를 생성한다.
. useradd: 리눅스에서 사용자를 생성하는 명령어
. passwd: 비밀번호를 변경하는 명령어
[root@victim ~]# useradd -g users oracleuser
[root@victim ~]# passwd oracleuser
cmd에서
C:\Users\ITSC>del .ssh\known_hosts
C:\Users\ITSC>ssh -L 1522:172.17.0.2:1521 oracleuser@192.168.100.10 -f -N
sql developer에 호스트 이름을 localhost로 바꾸면 접속이 가능하다.
3. 실제 접속 설정
보안 강화를 위해서 아래 내용들을 설정해야 한다.
. 사용자의 셸 수정
- /bin/bash -> /bin/false
. 백그라운 프로세스로 실행
- -f -N 옵션 사용
Tomcat 설치하기
[root@victim ~]# systemctl stop tomcat.service
[root@victim ~]# docker run -d --restart=always \
-p 8080:8080 -p 8009:8009 \
-e LC_ALL=C.UTF-8 \
-v /home/tomcat:/usr/local/tomcat/webapps/ROOT/ \
--name tomcat9.0 \
tomcat:9.0
볼륨 마운트
. 컨테이너 생성을 할 때 Host OS에 /home/tomcat 이 Container의 /usr/local/tomcat/webapps/ROOT/ 와 연결되어 있다.
docker run 명령어의 옵션
. docker run
- local 에 이미지가 없으면 pull + run 명령어이다.
. -d : 데몬 모드
. -it : 입출력: 이미지를 다운받고 컨테이너 생성 후 컨테이너 안으로 들어간다
. -p 8080:8080 -p 8009:8009
- Host OS 포트와 컨테이너 포트를 동기화할 때 사용한다.
. -e LC_ALL=C.UTF-8 : utf-8 한글입력 가능
. -v /home/tomcat:/usr/local/tomcat/webapps/ROOT/
- Host OS 디렉터리와 컨테이너 디렉터리와의 파일을 동기화한다.
- 웹 소스 파일을 컨터이너에서 빼서 Host OS의 디렉터리로 빼내는 작업을 한다.
- 나중에 컨테이너를 삭제해도 Host OS의 소스 파일을 삭제되지 않는다.
. --name tomcat9.0 : 컨테이너 이름
. tomcat:9.0 : 이미지 이름
로그인해서 dockerps를 사용하기 위해서 자신의 홈디렉터리에 .bashrc 파일에 넣어준다.
[root@docker ~]# vi .bashrc
:
alias dockerps='docker ps --format "table {{.ID}}\t{{.Image}}\t{{.Ports}}\t{{.Names}}"'
2. jdbcdrivertest
[root@victim ~]# cd /home/tomcat/
[root@victim tomcat]# vi jdbcdrivertest.jsp
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8" %>
<%@ page import="java.sql.*" %>
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>::: Oracle JDBC 드라이버 테스트 :::</title>
</head>
<body>
<%
try {
Class.forName("oracle.jdbc.OracleDriver");
out.println("드라이버 로드 성공<br>");
} catch (ClassNotFoundException e) {
out.println("드라이버 로드 실패<br>");
e.printStackTrace(out);
}
%>
</body>
</html>
JDBC 드라이버가 없으면 드라이버 로드 실패 메세지가 출력된다.
http://192.168.100.10:8080/jdbcdrivertest.jsp
[root@victim tomcat]# docker exec -it tomcat9.0 bash
JDBC 드라이버가 없으면 드라이버 로드 실패 메세지가 출력된다.
http://192.168.100.10:8080/jdbcdrivertest.jsp
Docker인 경우
. Docker 안에 JDBC 드라이버를 아래처럼 복사한다.
- [Docker oracle11gxe] ---> [Docker tomcat9.0]
- oracle11gxe: /u01/app/oracle/product/11.2.0/xe/jdbc/lib/ojdbc6.jar
- tomcat9.0: /usr/local/tomcat/lib
- Docker oracle11gxe에 오라클이 설치된 디렉터리에 JDBC 드라이버가 존재한다.
- JDBC 드라이버를 Docker tomcat9.0의 [톰캣 디렉터리]/lib/ojdbc6.jar 로 복사한다.
- Docker tomcat9.0을 재시한다.
[root@victim tomcat]# docker cp oracle11gxe:/u01/app/oracle/product/11.2.0/xe/jdbc/lib/ojdbc6.jar . <= 오라클 컨테이너에서 호스트로 복사
[root@victim tomcat]# docker cp ojdbc6.jar tomcat9.0:/usr/local/tomcat/lib <= 호스트에서 톰캣 컨테이너로 복사한걸 보냄
[root@victim tomcat]# docker restart tomcat9.0
. Docker에서 파일 복사 방식
- 호스트 -> 컨테이너: 복사 가능
- 컨테이너 -> 호스트: 복사 가능
- 컨테이너 -> 컨테이너: 복사 불가능
- 컨테이너끼리 복사를 하면 에러가 발생한다.
copying between containers is not supported <-- 컨테이너 → 컨테이너 직접 복사는 지원되지 않는다.
JDBC 드라이버가 있으면 드라이버 로드 성공 메세지가 출력된다.
http://192.168.100.10:8080/jdbcdrivertest.jsp
드라이버 로드 성공
3. getemp.jsp 작성
[root@victim tomcat]# vi getemp.jsp
<%--
파일명: getemp.jsp
프로그램 설명: EMP 테이블의 내용을 출력한다.
--%>
<%@ page import="java.sql.DriverManager"%>
<%@ page import="java.sql.ResultSet"%>
<%@ page import="java.sql.Statement"%>
<%@ page import="java.sql.Connection"%>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%!
// 변수 선언
//String dbhost = "jdbc:oracle:thin:@oracle11gxe:1521:XE";
String dbhost = "jdbc:oracle:thin:@192.168.100.10:1521:XE";
String dbuser = "scott";
String dbpass = "tiger";
String query = "SELECT * FROM EMP";
String title = "::: EMP 테이블 출력하기 :::";
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title> <%=title%> </title>
<style>
table {
margin-left:auto;
margin-right:auto;
width: 800px;
border: 1px solid #444444;
border-collapse: collapse;
}
tr, td {
border: 1px solid #444444;
padding: 7px;
}
</style>
</head>
<body>
<table>
<tr align="center">
<td align="center" colspan="8"> 테이블명: EMP (사원 테이블) </td>
</tr>
<tr align="center" bgcolor="#ffffff">
<td align="center"> 사원 번호 </td>
<td align="center"> 사원 이름 </td>
<td align="center"> 사원 직책 </td>
<td align="center"> 직속 상관 </td>
<td align="center"> 입사일 </td>
<td align="center"> 급여 </td>
<td align="center"> 추가 수당 </td>
<td align="center"> 부서 번호 </td>
</tr>
<%
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
} catch (ClassNotFoundException e ) {
e.printStackTrace();
}
try {
conn = DriverManager.getConnection(dbhost, dbuser, dbpass);
stmt = conn.createStatement();
rs = stmt.executeQuery(query);
// EMP 테이블에서 자료가 없을 때 까지 출력한다.
while (rs.next())
{
// EMP 테이블에서 자료를 가져오는 부분
String EMPNO = rs.getString("EMPNO"); // 컬럼명으로 가져오기
String ENAME = rs.getString("ENAME");
String JOB = rs.getString("JOB");
String MGR = rs.getString(4); // 컬럼의 순서로 가져오기
String HIREDATE = rs.getString(5);
String SAL = rs.getString(6);
String COMM = rs.getString(7);
String DEPTNO = rs.getString(8);
// 가져온 데이터를 브라우저에 출력하는 부분
out.print("<tr align=\"center\" bgcolor=\"#ffffff\">" +
"<td>" + EMPNO + "</td>" +
"<td>" + ENAME + "</td>" +
"<td>" + JOB + "</td>" +
"<td>" + MGR + "</td>" +
"<td>" + HIREDATE + "</td>" +
"<td>" + SAL + "</td>" +
"<td>" + COMM + "</td>" +
"<td>" + DEPTNO + "</td>" +
"</tr>");
}
} catch ( Exception e ) {
e.printStackTrace();
} finally {
try {
rs.close();
stmt.close();
conn.close();
} catch ( Exception e ) {
e.printStackTrace();
}
}
%>
</table>
</body>
</html>
4. 접속
emp 테이블의 내용이 출력된다.
http://192.168.100.10:8080/getemp.jsp
Docker network
IP주소를 172.17.0.0으로 잡으면 도커에 실행 순서에 따라 IP주소가 바뀌기 때문에 접속이 안될수도 있다
그래서 네트워크를 만들어 고정 IP처럼 사용한다
서버의 네트워크를 확인한다.
[root@victim ~]# ip -br -4 a
사용자 정의 네트워크 생성(고정 IP용)
명령어 설명
. docker network create
- Docker에 새 네트워크를 생성한다.
- 생성된 네트워크는 이후 docker run --network mynetwork ... 형태로 컨테이너를 붙일 때 사용한다.
. --driver bridge
- 네트워크 드라이버를 bridge로 지정한다.
- 한 대의 서버(단일 호스트)에서 컨테이너끼리 통신시키는 가장 일반적인 방식이다.
- 이 네트워크를 생성하면 리눅스에 브리지 인터페이스(br-<네트워크ID>)가 새로 생성된다.
- br-<네트워크ID> 에서 네트워크ID는 랜덤으로 생성되므로 각자 다르다.
. --subnet 172.30.10.0/24
- 네트워크에서 사용할 IP 대역(서브넷) 을 지정한다.
- /24는 대역 크기(네트워크 주소: 172.30.10.0, 브로드캐스트주소: 172.30.10.255)
- 컨테이너에 할당 가능한 범위(Host OS: 172.30.10.1, 172.30.10.2 ~ 172.30.10.254)
- Docker는 이 범위 내에서 컨테이너에 IP를 자동 할당하거나(동적), 고정으로 사용할 수 있다.
- --ip 옵션을 이용해서 컨테이너에 고정으로 IP주소를 할당할 수 있다.
. --gateway 172.30.10.1
- 해당 서브넷에서 게이트웨이 IP(기본 라우터 역할)를 지정한다.
- Docker가 만든 브리지 인터페이스가 이 주소를 할당 받는다.
- 컨테이너 관점에서는 172.30.10.1이 “기본 게이트웨이”가 되어서 NAT 통신을 한다.
. mynetwork
- 생성될 네트워크의 이름으로 자유롭게 설정할 수 있다.
[root@victim ~]# docker network create --driver bridge \
--subnet 172.30.10.0/24 \
--gateway 172.30.10.1 \
mynetwork
[root@victim ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
...
8457b1611de4 mynetwork bridge local
도커 네트워크가 생성되면 인터페이스가 1개 생성된다.
[root@victim ~]# ip -br -4 a
자세한 정보를 보려면 아래 inspect 를 사용한다.
[root@victim ~]# docker network inspect mynetwork
[root@victim ~]# docker run -d --name mariadb \
--restart=always \
--network mynetwork --ip 172.30.10.12 \
-e MARIADB_ROOT_PASSWORD=1 \
-e MARIADB_DATABASE=mydb \
-v mariadb_data:/var/lib/mysql \
mariadb:10.11
명령어 옵션 설명
Docker가 재실행되어도 컨테이너가 재시작하는 방법
. 신규 컨테이너 생성 시 적용하는 방법
- 형식: docker run ... --restart=always ...
- e.g.) docker run -d --restart=always --name apache_web_server -p 80:80 httpd
. 이미 실행중인 컨테이너에 적용하는 방법
- 형식: docker update --restart=always <컨테이너명>
- e.g.) docker update --restart=always apache_web_server
명령어 및 옵션 설명
. docker run
- 새 컨테이너를 생성하고 실행한다.
- 이미지가 없는 경우: 도커 레지스트리에서 다운로드 받는다.
- 이미지가 있는 경우: 다운 받은 이미지에서 컨테이너 인스턴스로 생성한다
. -d
- Detached 모드: 터미널을 점유하지 않고 백그라운드에서 실행하는 데몬모드이다.
- 실행 후 컨테이너 ID만 출력되고 프롬프트로 돌아온다.
. --name mariadb
- 컨테이너 이름을 mariadb로 설정한다.
- 컨테이너에 이름을 설정하면 컨테이너의 이름으로 제어할 수 있다.
e.g.) docker logs mariadb, docker exect -it mariadb ...
- 이 옵션이 없을 경우 랜덤으로 자동 생성된다.
- 사용자 정의 네트워크에서는 이 이름이 내부 DNS 이름으로도 동작하기 때문에
다른 컨테이너에서 mariadb:3306 으로 접근이 가능하게 된다.
. --restart=always
- 서버가 부팅되거나 Docker를 재실행해도 컨테이너가 시작된다.
. --network mynetwork
- 컨테이너를 Docker 네트워크 mynetwork에 연결한다.
- 같은 네트워크에 있는 컨테이너끼리는 사설 IP 주소로 직접 통신이 가능하다.
. --ip 172.30.10.12
- mynetwork에서 이 컨테이너에 할당될 고정 IPv4 주소를 설정한다.
- 전제 조건
mynetwork가 172.30.10.0/24 같은 서브넷으로 만들어져 있어야 한다.
해당 IP주소가 다른 컨테이너/장비와 중복되면 충돌된다.
. -e MARIADB_ROOT_PASSWORD=1
- 컨테이너 내부 초기화 스크립트에 전달되는 환경 변수이다.
- MariaDB 공식 이미지의 엔트리포인트가 "데이터 디렉터리가 비어있을 때(첫 실행)" 이 값을 사용해서 root 계정 비밀번호를 설정한다.
- 여기서는 연습용이므로 1로 설정하는 것이지만 실제로 사용할 때는 강한 비밀번호를 설정하기를 권장한다.
. -e MARIADB_DATABASE=mydb
- 첫 초기화 시 mydb 데이터베이스를 자동으로 생성한다.
- 이것도 "첫 초기화(빈 데이터 디렉터리)" 시점에만 적용되는 것이 일반적이다.
. -v mariadb_data:/var/lib/mysql
- 볼륨 마운트로 컨터이너에 있는 DB를 Host OS로 연결한다. (영구 저장)
-v mariadb_data:/var/lib/mysql
- 호스트 디렉터리를 사용할 때
절대 경로: /var/test/mysql 설정하면 /var/test/에 mysql 디렉터리가 생성된다.
[root@docker ~]# ls -ld /var/test/mysql/
drwxr-xr-x. 6 systemd-coredump systemd-coredump 4096 Dec 17 10:51 /var/test/mysql/
상대 경로: mariadb_data 만들면 /var/lib/docker/volumes/ 디렉터리에 mariadb_data 디렉터리가 생성된다.
[root@docker ~]# ls -ld /var/lib/docker/volumes/mariadb_data/
drwx-----x. 3 root root 19 Dec 17 09:49 /var/lib/docker/volumes/mariadb_data/
. mariadb:10.11
- 사용할 이미지와 태그이다.
[root@victim ~]# systemctl stop mariadb
[root@victim ~]# docker exec -it mariadb bash
패스워드를 설정해뒀기 때문에 mysql 실행시 -p로 패스워드를 입력한다
root@bad3157cc7fc:/# mysql -p1
root@633766df7780:/# cd
cat << EOF > .my.cnf
[client]
host = localhost
user = root
password = 1
EOF
wordpress 설치
[root@victim ~]# systemctl stop httpd.service
[root@victim ~]# docker run -d --name wordpress \
--restart=always \
--network mynetwork --ip 172.30.10.13 \
-p 80:80 \
-e WORDPRESS_DB_HOST='172.30.10.12:3306' \
-e WORDPRESS_DB_USER='root' \
-e WORDPRESS_DB_PASSWORD=1 \
-e WORDPRESS_DB_NAME='mydb' \
-v wp_data:/var/www/html \
wordpress:latest
도커 네트워크를 이용해 고정 IP주소로 설정하기
--조건 --
1. Docker network 생성
. tomcatoracle
- 172.17.20.0/24
[root@ docker ~]# docker network create --driver bridge \
--subnet 172.20.20.0/24 \
--gateway 172.20.20.1 \
tomcatoracle
2. Oracle 11gXE
. 컨테이너 이름
- oracle11gxe
- IP Address: 172.20.20.2/24
[root@docker ~]# docker run -d --restart=always -p 1521:1521 \
--network tomcatoracle --ip 172.20.20.2 \ <= 고정 네트워크 할당
--name oracle11gxe oracleinanutshell/oracle-xe-11g
[root@docker ~]# dnf -y install wget
[root@docker ~]# wget linuxmaster.net/scott.sql.txt
[root@docker ~]# docker cp scott.sql.txt oracle11gxe:/root
[root@docker ~]# docker exec -it oracle11gxe bash
root@f23d35c94108:/# sqlplus sys/oracle as sysdba
SQL> @/root/scott.sql.txt
SQL> exit
root@f23d35c94108:/# exit
3. Tomcat
. 컨테이너 이름
- tomcat9
- IP Address: 172.20.20.3/24
[root@ docker ~]# docker run -d --restart=always \
--network tomcatoracle --ip 172.20.20.3 \
-p 8080:8080 -p 8009:8009 \
-e LC_ALL=C.UTF-8 \
-v /home/tomcat:/usr/local/tomcat/webapps/ROOT/ \
--name tomcat9.0 \
tomcat:9.0
4. JDBC 드라이버 연동
[root@docker ~]# docker cp oracle11gxe:/u01/app/oracle/product/11.2.0/xe/jdbc/lib/ojdbc6.jar .
[root@docker ~]# docker cp ojdbc6.jar tomcat9.0:/usr/local/tomcat/lib
[root@docker ~]# docker restart tomcat9.0
5. getemp.jsp
[root@ docker tomcat]# vi getemp.jsp
<%--
파일명: getemp.jsp
프로그램 설명: EMP 테이블의 내용을 출력한다.
--%>
<%@ page import="java.sql.DriverManager"%>
<%@ page import="java.sql.ResultSet"%>
<%@ page import="java.sql.Statement"%>
<%@ page import="java.sql.Connection"%>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%!
// 변수 선언
String dbhost = "jdbc:oracle:thin:@oracle11gxe:1521:XE";
String dbuser = "scott";
String dbpass = "tiger";
String query = "SELECT * FROM EMP";
String title = "::: EMP 테이블 출력하기 :::";
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title> <%=title%> </title>
<style>
table {
margin-left:auto;
margin-right:auto;
width: 800px;
border: 1px solid #444444;
border-collapse: collapse;
}
tr, td {
border: 1px solid #444444;
padding: 7px;
}
</style>
</head>
<body>
<table>
<tr align="center">
<td align="center" colspan="8"> 테이블명: EMP (사원 테이블) </td>
</tr>
<tr align="center" bgcolor="#ffffff">
<td align="center"> 사원 번호 </td>
<td align="center"> 사원 이름 </td>
<td align="center"> 사원 직책 </td>
<td align="center"> 직속 상관 </td>
<td align="center"> 입사일 </td>
<td align="center"> 급여 </td>
<td align="center"> 추가 수당 </td>
<td align="center"> 부서 번호 </td>
</tr>
<%
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
} catch (ClassNotFoundException e ) {
e.printStackTrace();
}
try {
conn = DriverManager.getConnection(dbhost, dbuser, dbpass);
stmt = conn.createStatement();
rs = stmt.executeQuery(query);
// EMP 테이블에서 자료가 없을 때 까지 출력한다.
while (rs.next())
{
// EMP 테이블에서 자료를 가져오는 부분
String EMPNO = rs.getString("EMPNO"); // 컬럼명으로 가져오기
String ENAME = rs.getString("ENAME");
String JOB = rs.getString("JOB");
String MGR = rs.getString(4); // 컬럼의 순서로 가져오기
String HIREDATE = rs.getString(5);
String SAL = rs.getString(6);
String COMM = rs.getString(7);
String DEPTNO = rs.getString(8);
// 가져온 데이터를 브라우저에 출력하는 부분
out.print("<tr align=\"center\" bgcolor=\"#ffffff\">" +
"<td>" + EMPNO + "</td>" +
"<td>" + ENAME + "</td>" +
"<td>" + JOB + "</td>" +
"<td>" + MGR + "</td>" +
"<td>" + HIREDATE + "</td>" +
"<td>" + SAL + "</td>" +
"<td>" + COMM + "</td>" +
"<td>" + DEPTNO + "</td>" +
"</tr>");
}
} catch ( Exception e ) {
e.printStackTrace();
} finally {
try {
rs.close();
stmt.close();
conn.close();
} catch ( Exception e ) {
e.printStackTrace();
}
}
%>
</table>
</body>
</html>
>scp jumsu.war admin@192.168.100.23:
[root@ docker ~]# cp /home/admin/jumsu.war .
혹은 tomcat 메니저로 war 파일을 올린다
root@1806de65757a:/usr/local/tomcat# apt update
root@1806de65757a:/usr/local/tomcat# apt -y install vim
root@1806de65757a:/usr/local/tomcat# vi conf/tomcat-users.xml
...
<user username="role1" password="<must-be-changed>" roles="role1"/>
-->
<role rolename="manager-gui"/>
<role rolename="manager-script"/>
<role rolename="manager-status"/>
<role rolename="admin-gui"/>
<user username="admin" password="tomcat1234" roles="manager-gui,manager-script,manager-status,admin-gui"/>
</tomcat-users>
root@1806de65757a:/usr/local/tomcat# cp -r /usr/local/tomcat/webapps.dist/manager /usr/local/tomcat/webapps/
manager는 기본적으로 localhost에서만 접속 가능하도록 제한되어 있기 때문에 192.168.100.1에서 접속할 수 있도록
설정한다.
root@1806de65757a:/usr/local/tomcat# vi /usr/local/tomcat/webapps/manager/META-INF/context.xml
<Context antiResourceLocking="false" privileged="true" >
<CookieProcessor className="org.apache.tomcat.util.http.Rfc6265CookieProcessor"
sameSiteCookies="strict" />
<Valve className="org.apache.catalina.valves.RemoteCIDRValve"
allow="127.0.0.0/8,::1/128,192.168.100.1/24" />
<Manager sessionAttributeValueClassNameFilter="java\.lang\.(?:Boolean|Integer|Long|Number|String)|org\.apache\.catalina\.filters\.CsrfPreventionFilter\$LruCache(?:\$1)?|java\.util\.(?:Linked)?HashMap"/>
</Context>
root@1806de65757a:/usr/local/tomcat# exit
Rocky Linux 9 Docker Host에서 실행한다.
[root@docker ~]# docker restart tomcat9.0
http://192.168.100.24:8080/manager/html
애플리케이션 접속
SQLDeveloper 접속 설정
Oracle sqldeveloper / DBever 를 사용해서 DBMS에 접속한다
SQLDeveloper 로 접속한 후 아래 JUMSU DB를 생성한다.
DROP TABLE JUMSUMEMBER PURGE;
CREATE TABLE JUMSUMEMBER
(
NO NUMBER(4), -- 번호
USERNAME VARCHAR2(30) NOT NULL, -- 회원명
USERID VARCHAR2(30) NOT NULL, -- 아이디
USERPW VARCHAR2(20) NOT NULL, -- 비밀번호
REGDATE DATE, -- 가입날짜
CONSTRAINT JUMSUMEMBER_NO_PK PRIMARY KEY(NO),
CONSTRAINT JUMSUMEMBER_USERID_UK UNIQUE(USERID)
);
-- JUMSUMEMBER_SEQ 시퀀스 생성
DROP SEQUENCE JUMSUMEMBER_SEQ;
CREATE SEQUENCE JUMSUMEMBER_SEQ;
-- JUMSUMEMBER 테이블 코멘트 설정
COMMENT ON TABLE JUMSUMEMBER IS '회원테이블';
COMMENT ON COLUMN JUMSUMEMBER.NO IS '번호';
COMMENT ON COLUMN JUMSUMEMBER.USERNAME IS '회원명';
COMMENT ON COLUMN JUMSUMEMBER.USERID IS '아이디';
COMMENT ON COLUMN JUMSUMEMBER.USERPW IS '비밀번호';
COMMENT ON COLUMN JUMSUMEMBER.REGDATE IS '가입날짜';
-- JUMSU 테이블 생성
DROP TABLE JUMSU PURGE;
CREATE TABLE JUMSU
(
NO NUMBER(4) NOT NULL, -- 번호
USERID VARCHAR2(30) NOT NULL, -- 이름
KOR NUMBER(3) NOT NULL, -- 국어점수
ENG NUMBER(3) NOT NULL, -- 영어점수
MATH NUMBER(3) NOT NULL, -- 수학점수
TOTAL NUMBER(3) NOT NULL, -- 총점
AVERAGE NUMBER(5,2) NOT NULL, -- 평균
REGDATE DATE, -- 저장날짜
CONSTRAINT JUMSU_NO_PK PRIMARY KEY(no),
CONSTRAINT JUMSU_USERID_FK FOREIGN KEY(userid) REFERENCES JUMSUMEMBER(userid)
);
-- JUMSUMEMBER 시퀀스 생성
DROP SEQUENCE JUMSU_SEQ;
CREATE SEQUENCE JUMSU_SEQ;
-- JUMSU 테이블 코멘트 설정
COMMENT ON TABLE JUMSU IS '점수테이블';
COMMENT ON COLUMN JUMSU.NO IS '번호';
COMMENT ON COLUMN JUMSU.USERID IS '아이디';
COMMENT ON COLUMN JUMSU.KOR IS '국어점수';
COMMENT ON COLUMN JUMSU.ENG IS '영어점수';
COMMENT ON COLUMN JUMSU.MATH IS '수학점수';
COMMENT ON COLUMN JUMSU.TOTAL IS '총점';
COMMENT ON COLUMN JUMSU.AVERAGE IS '평균';
COMMENT ON COLUMN JUMSU.REGDATE IS '가입날짜';
-- 코멘트 조회
--SELECT * FROM ALL_COL_COMMENTS WHERE TABLE_NAME = 'JUMSUMEMBER';
--SELECT * FROM ALL_COL_COMMENTS WHERE TABLE_NAME = 'JUMSU';
-- 시퀀스 조회
--SELECT * FROM USER_SEQUENCES;
이클립스를 실행해서 DB 접속 부분을 docker 로 수정해야 한다.
<%--
dbConnect.jsp
DB 접속 정보
--%>
<%
//String dbhost = "jdbc:oracle:thin:@localhost:1521:XE";
String dbhost = "jdbc:oracle:thin:@oracle11gxe:1521:XE";
String dbuser = "scott";
String dbpass = "tiger";
%>
Nginx Reverse Proxy로 Tomcat 8080 연결하기
요청 흐름
. 사용자 브라우저 -> 192.168.100.24:80 -> nginx-proxy 컨테이너 -> tomcat9.0:8080 -> Tomcat 웹 애플리케이션 실행
프록시와 리버스프록시 차이
. 리버스 프록시는 외부 요청의 "입구(게이트웨이)" 역할을 하면서 내부 서비스로 안전하게 라우팅해주는 프론트 서버이다.
. 정방향(Forward) 프록시: 내부 사용자가 외부로 나갈 때 프록시 서버가 받아서 대신 나간다.
e.g.) 회사에서 직원 PC → 프록시 서버 → 인터넷, iptables의 SNAT를 생각하자
. 리버스(Reverse) 프록시: 외부 사용자가 내부 서버로 들어올 때 앞에서 프록시 서버가 대신 받는다.
e.g.) 인터넷 사용자 → Nginx → 내부의 WordPress/DB/, iptables DNAT를 생각하자.
[root@docker ~]# mkdir -p /root/nginx-proxy/conf.d
[root@docker ~]# vi /root/nginx-proxy/conf.d/tomcat.conf
server {
listen 80;
server_name 192.168.100.24;
location / {
proxy_pass http://tomcat9.0:8080;
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-Proto $scheme;
}
}
[root@docker ~]# docker run -d \
--name nginx-proxy \
--network tomcatoracle \
--ip 172.20.20.4 \
-p 80:80 \
-v /root/nginx-proxy/conf.d:/etc/nginx/conf.d:ro \
nginx
nginx-proxy 컨테이너 안에서 Nginx 설정 검사를 실행한다.
[root@docker ~]# docker exec nginx-proxy nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok <-- Nginx 설정 파일 문법이 정상
nginx: configuration file /etc/nginx/nginx.conf test is successful <-- 설정 파일 전체 검사가 성공