• docker0 인터페이스 자동재시작 스크립트
sudo tee /root/check_ip_and_restart_docker.sh<<EOF
#!/bin/bash
 
if ! ip add | grep -q 172.17; then
systemctl restart docker
fi
EOF
root@host:~# chmod 777 /root/check_ip_and_restart_docker.sh
  • 스케쥴 관리. 2번 기본 vim 편집기
root@host:~# crontab -e
* * * * * /root/check_ip_and_restart_docker.sh

♨ 나는 왜 vim으로 열리지 않는가...

nano 편집기로 열려서 일반 vim 편집기로 바꾸려면 crontab -e 실행 시 사용하는 기본 편집기를 변경

vi ~/.bashrc
export VISUAL=vim
export EDITOR=vim
source ~/.bashrc

  • yaml 두칸 들여쓰기, 엔터치면 바로 아래서 입력되도록
vi ~/.vimrc
" Enable file type detection
filetype on

" Enable syntax highlighting
syntax on

" Enable auto-indentation for YAML files
autocmd FileType yaml setlocal autoindent smartindent expandtab shiftwidth=2 tabstop=2
autocmd FileType yml setlocal autoindent smartindent expandtab shiftwidth=2 tabstop=2

Docker compose

  • docker - 단일 호스트에서 단일컨테이너를 생성(docker run)
  • docker compose - 단일 호스트에서 여러개의 컨테이너를 동시 생성(docker compose up)

  • yaml을 통해 내가 띄울 여러개의 컨테이너를 정의
root@host:~# mkdir /compose
root@host:~# cd /compose/
root@host:/compose# vi web.yml
services:
#내가 띄울 다양한 종류의 컨테이너들
  webserver:
#서비스의 이름
    image: nginx
    ports:
    - '8787:80'
# -p옵션과 비슷
    networks:
    - webnet
# 밑에서 생성한 네트워크 선택
networks:
  webnet:
# 네트워크 생성

root@host:/compose# mv web.yml docker-compose.yml
root@host:/compose# docker compose up

# 우리가 컴포즈파일에서 정의한 webnet이라는 네트워크가 생성된걸 알 수 있다.

 

 

  • 내용 추가
root@host:/compose# vi docker-compose.yml
volumes:
    - ./vtest:/usr/share/nginx/html
#호스트의 ./vtest를 컨테이너의 /usr/share/nginx/html에 마운트

root@host:/compose# docker compose up -d
root@host:/compose# echo vtest > vtest/index.html


docker-compose.yml 명령어

  • 네트워크 정의 및 선택
networks:
  • -p, publish 옵션
ports:
  • CMD
command:
  • -e, 환경변수
environment:
  • A라는 서비스에 B에 대한 depends_on을 걸어주면, B 먼저 생성 후 A가 생성
depends_on:

ex) nodejs 앱(todo,weather, chat) 의 경우 몽고디비가 연동이 안되면 앱 자체가 죽어버림.

nodejs 서비스를 생성하면서 몽고디비를 depends_on으로 걸어야함.


실습)

위 명령어를 활용하여, ubuntu:latest를 동작시키는 compose 파일을 만들어보세요.
네트워크 : ubun_net
root@host:/compose# mkdir ubuntu
root@host:/compose# cd ubuntu/
root@host:/compose/ubuntu# vi docker-compose.yml
services:
#내가 띄울 다양한 종류의 컨테이너들
  ubun:
#서비스의 이름
    image: ubuntu:latest
    networks:
    - ubun_net
    command: "sleep 200"
networks:
  ubun_net:
root@host:/compose/ubuntu# docker compose up -d
    command: "sleep infinity"

  • 환경변수 추가
    environment:
      ENV_TEST: 'test'

# 둘다 ㄱㅊ

root@host:/compose/ubuntu# docker exec -it ubuntu-ubun-1 bash

 

docker의 --link 옵션

도커 컴포즈에서는 --link를 굳이 명시하지 않아도 서비스의 이름으로 찾아갈 수 있다.


실습)

wordpress, mysql:8, wordpress:latest를 베이스이미지로하여 Dockerfile은 쓰지않고 docker-compose.yml 파일을 구성해보세요. publish 포트는 wordpress 1234로 하시고, mysql은 없다. 

각 서비스명
- wordpress: wp
- mysql: dbdb
root@host:/compose# mkdir wordpress
root@host:/compose# cd wordpress/
root@host:/compose/wordpress# vi docker-compose.yml
services:
  wp:
    image: wordpress:latest
    ports:
    - '1234:80'
    environment:
      WORDPRESS_DB_HOST: dbdb
      WORDPRESS_DB_USER: wpuser
      WORDPRESS_DB_PASSWORD: '1234'
      WORDPRESS_DB_NAME: wpdb
    networks:
    - wpdb
    depends_on:
    - dbdb
  dbdb:
    image: mysql:8
    environment:
      MYSQL_ROOT_PASSWORD: '1234'
      MYSQL_DATABASE: wpdb
      MYSQL_USER: wpuser
      MYSQL_PASSWORD: '1234'
    networks:
    - wpdb
networks:
  wpdb:
  • docker-compose가 서비스의 이름으로 찾아갈 수 있도록 알아서 관리
services:
  wp:
    image: wordpress:latest
    ports:
    - '1234:80'
    environment:
    - WORDPRESS_DB_HOST=dbdb
    - WORDPRESS_DB_NAME=wpdb
    - WORDPRESS_DB_USER=wpuser
    - WORDPRESS_DB_PASSWORD=1234
    networks:
    - wpnet
# 네트워크를 명시하지 않으면 스스로 만든다.
    depends_on:
    - dbdb
  dbdb:
    image: mysql:8
    environment:
    - MYSQL_ROOT_PASSWORD=1234
    - MYSQL_USER=wpuser
    - MYSQL_PASSWORD=1234
    - MYSQL_DATABASE=wpdb
    networks:
    - wpnet

networks:
  wpnet:


이미 존재하는 네트워크를 선택하고 싶을 때

  • 미리 네트워크를 생성
root@host:/compose/wordpress# docker network create wpnet --driver=bridge

root@host:/compose/wordpress# docker network inspect wpnet

이번에는 컴포즈파일에서 이 네트워크를 선택해서 리소스를 띄워보자.

root@host:/compose/wordpress# vi docker-compose.yml 

# 위에서 생성한 네트워크(이미 존재하는 네트워크)를 매칭


서비스에서 이미지를 빌드하는 방법

  • 기존꺼 삭제
root@host:/compose/wordpress# docker compose down
root@host:/compose# mkdir build
root@host:/compose# cd build/
root@host:/compose/build# vi docker-compose.yml
services:
  dbdbdb:
    build:
#이미지빌드하겠다. 현재디렉토리에 Dockerfile이 있으면 그냥 build:로 가능
      context: .
#현재디렉토리(.)
      dockerfile: Dockerfile
#도커 파일 이름 지정
    image: mydb:1
#빌드해서 나온 이미지 이름
    ports:
      - '33306:3306'
root@host:/compose/build# vi Dockerfile
FROM mysql:8
ENV MYSQL_DATABASE=wpdb
ENV MYSQL_USER=wpuser
ENV MYSQL_PASSWORD=12345
ENV MYSQL_ROOT_PASSWORD=1234
apt install -y mysql-client-core-8.0
root@host:/compose/build# mysql -u wpuser -p1234 -h 211.183.3.150 -P 33306

# 암호가 업뎃이 안됐다  = 이미지 빌드가 안됐다 = 이미지가 이미 존재하면 빌드를 안한다

root@host:/compose/build# docker compose down
  • 항상 빌드하게 하는 옵션
root@host:/compose/build# docker compose up --build -d

# 12345로 접속 가능


docker compose scaling

  • --scale <서비스이름>=<컨테이너갯수>
root@host:/compose/build# docker compose up --scale dbdbdb=3 -d

# 호스트의 publish된 포트는 1개밖에 없기 때문에 compose에서 호스트포트의 범위를 늘려야 한다.

  • 호스트의 포트를 넉넉하게


실습)

https://docs.docker.com/compose/gettingstarted/

위 예제를 통해 web-redis 컨테이너를 컴포즈파일로 만들어보세요.
  • 파일구성 후 docker compose up

  • 스케일링을 위해 compose 파일 수정 docker-compose.yml

# redis: 캐싱 가능


실습)

https://github.com/oolralra/vue-fastapi.git

지난 시간에 했던 vuejs-fastapi 앱을 docker compose로 구성해보세요.
root@host:/compose/multi/vue-fastapi# vi docker-compose.yml
services:
  frontend:
    build:
      context: ./frontend/
    ports:
    - '85-88:80'
    depends_on:
    - backend
  backend:
    build:
      context: ./backend/
    ports:
    - '8000-8005:8000'

풀이)

root@host:/compose# git clone https://github.com/oolralra/vue-fastapi.git

root@host:/compose# cd vue-fastapi

root@host:/compose/vue-fastapi# vi frontend/Dockerfile

# 내용 확인

root@host:/compose/vue-fastapi# vi docker-compose.yml
services:
  backend:
#소스코드에서 backend:8000으로 찾아가라고 되어있기때문에
#서비스의 이름을 이걸로 해야함.
    build:
      context: ./backend
    image: vuejs:1

  frontend:
    build:
      context: ./frontend
    image: backimg:1
    ports:
    - '81:80'
    depends_on:
    - backend


실습)

아래와 같이 디렉토리 구성후 web은 nginx, was는 tomcat, db는 mysql:8로 3 tier를 구성하는 도커컴포즈 파일을 작성하세요! curl 211.183.3.150:4989 로 접속했을때 DB연동을 확인해보세요!

root@host:/compose/3tier# apt install -y tree

풀이1)

web(nginx) → was(tomcat) → db(mysql)로 요청 흐름

  • docker-compose.yml
root@host:/compose/3tier# vi docker-compose.yml
services:
  web:
    build: ./web/
    ports:
    - "4989:80"
    depends_on:
    - was
    networks:
    - mynetwork

  was:
    build: ./was/
    ports:
    - "8080:8080"
    depends_on:
    - db
    networks:
    - mynetwork

  db:
    build: ./db/
    environment:
      MYSQL_ROOT_PASSWORD: "1234"
      MYSQL_DATABASE: "tomdb"
      MYSQL_USER: "tomuser"
      MYSQL_PASSWORD: "1234"
    ports:
      - "3306:3306"
    volumes:
    - ./db/data:/var/lib/mysql
    networks:
    - mynetwork

networks:
  mynetwork:
    driver: bridge

 

/web

  • Dockerfile
FROM nginx:latest
COPY default.conf /etc/nginx/conf.d/default.conf
  • default.conf
server {
    listen 80;

    location / {
        proxy_pass http://was: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;
    }
}

 

/was

  • JDBC 드라이버 다운로드
root@host:/compose/3tier/was# wget https://repo1.maven.org/maven2/mysql/mysql-connector-java/8.0.23/mysql-connector-java-8.0.23.jar
  • Dockerfile
FROM tomcat:latest
WORKDIR /usr/local/tomcat
RUN mkdir -p /usr/local/tomcat/webapps/ROOT
COPY index.jsp /usr/local/tomcat/webapps/ROOT/index.jsp
COPY dbtest.jsp /usr/local/tomcat/webapps/ROOT/dbtest.jsp
COPY mysql-connector-java-8.0.23.jar /usr/local/tomcat/lib
  • index.jsp
root@host:/compose/3tier/was# echo '3-Tier Architecture' > index.jsp
  • dbtest.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ page import="java.sql.*"%>
<h1>DB</h2>
<%
        Connection conn=null;
        try{
                String Url="jdbc:mysql://db:3306/tomdb";
                String Id="tomuser";
                String Pass="1234";

                Class.forName("com.mysql.jdbc.Driver");
                conn=DriverManager.getConnection(Url,Id,Pass);
                out.println("was-db Connection Success!");
        }catch(Exception e) {
                e.printStackTrace();
}
%>

 

/db

  • Dockerfile
FROM mysql:8
ENV MYSQL_ROOT_PASSWORD=1234
ENV MYSQL_PASSWORD=1234
ENV MYSQL_USER=tomuser
ENV MYSQL_DATABASE=tomdb

 

빌드

root@host:/compose/3tier# docker compose down
root@host:/compose/3tier# docker compose up --build -d

풀이2)

 

1. db 구성

root@host:/compose/3tier# vi db/Dockerfile
FROM mysql:8
ENV MYSQL_ROOT_PASSWORD=1234
ENV MYSQL_PASSWORD=1234
ENV MYSQL_USER=tomuser
ENV MYSQL_DATABASE=tomdb

 

 

2. tomcat 구성

root@host:/compose/3tier# vi was/Dockerfile
FROM tomcat:latest
WORKDIR /usr/local/tomcat
RUN mkdir /usr/local/tomcat/webapps/ROOT
COPY dbtest.jsp ./webapps/ROOT/dbtest.jsp
COPY index.jsp ./webapps/ROOT/index.jsp
COPY mysql* /usr/local/tomcat/lib

# CMD는 이미 베이스이미지에 구성되어있으므로 안함

  • dbtest 파일 구성
root@host:/compose/3tier# vi was/dbtest.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ page import="java.sql.*"%>
<h1>DB</h2>
<%
        Connection conn=null;
        try{
                String Url="jdbc:mysql://db/tomdb";
                String Id="tomuser";
                String Pass="1234";

                Class.forName("com.mysql.jdbc.Driver");
                conn=DriverManager.getConnection(Url,Id,Pass);
                out.println("was-db Connection Success!");
        }catch(Exception e) {
                e.printStackTrace(); 
}
%>

  • 인덱스 파일 구성
root@host:/compose/3tier# cat was/index.jsp 
<%@ page contentType="text/html; charset=UTF-8"%>
<html>
     <head><title>hello world</title></head>
     <body>
     <h2>
             TOMCAT TEST<br><br>
             time : <%= new java.util.Date()%>
             <%@ page import="java.net.InetAddress" %><br>
             <%InetAddress inet= InetAddress.getLocalHost();%>
             WAS ip : <%=inet.getHostAddress()%>
     </h2>
     </body>
</html>

 

3. web 구성

root@host:/compose/3tier# cat web/default.conf
  • 리버스프록시 파일 구성
server {
location /jsp {
proxy_pass http://was:8080/;
}
}

root@host:/compose/3tier# cat web/Dockerfile 
FROM nginx:alpine
WORKDIR /etc/nginx/conf.d/
COPY default.conf default.conf

 

4. 컴포즈파일 구성

root@host:/compose/3tier# cat docker-compose.yml 
services:
  web:
    build:
      context: ./web
    image: tom-web:1
    ports:
    - '88:80'
    depends_on:
    - was
  was:
    build:
      context: ./was
    depends_on:
    - db
    image: tom-was:1
  db:
    build:
      context: ./db
    image: tom-db:1
root@host:/compose/3tier# docker compose up -d --build --scale was=3


자율과제)

todo/weather/chat 이것도 한번 docker compose로 만들어보세요.
몽고디비에 저장되는 데이터를 호스트의 ./mongo 에 저장시켜보세요. (volume)