Docker
- 1. Install Docker
- 2. Docker 101
- 3. Dockerfile
- 4. Networks
- 5. User defined networks
- SSH Service
- MariaDB
- 6. UFW Port Forward

Installing Docker on Ubuntu
[https://docs.docker.com/engine/install/ubuntu/][https://docs.docker.com/engine/install/ubuntu/]
1. Install Docker
1.1 Installing Docker Community Edition on Ubuntu
이전 버전의 docker를 지워줍니다.
sudo apt-get remove docker docker-engine docker.io
HTTPS를 통해 repository를 다운받을수 있도록 관련 패키지를 설치합니다.
$ sudo apt-get install apt-transport-https ca-certificates curl software-properties-common gnupg lsb-release
gpg 키를 등록시킵니다.
$ sudo mkdir -p /etc/apt/keyrings
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
Repository를 설치후 Docker Community Edition을 설치합니다.
$ echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
$ sudo apt-get update
$ sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin
1.2 Docker Configuration
1.2.1 docker group
기본적으로 Docker Deamon은 TCP Port대신에 Unix Socket으로 연결이 됩니다. Unix Socket은 root에 소유된 것이므로, Docker를 실행하기 위해서는 항상 반드시 sudo로 해주어야 합니다.
sudo를 피하기 위해서는 docker group을 만들어주고, 여기에 users 를 등록시켜주면 됩니다.
sudo groupadd docker
sudo usermod -aG docker $USER
로그 아웃후 다시 로그인 합니다.
잘되는지 확인은 다음과 같이 합니다.
docker run hello-world
1.2.2 Purge AppArmor
container를 삭제하려고 할때 permission denied 에러가 나올수 있는데, 이 경우 AppArmor 를 삭제해주면 됩니다.
# status 체크
sudo aa-status
# Shutdown 시키고 restarting 금지
sudo systemctl disable apparmor.service --now
# AppArmor 를 unload시킴
sudo service apparmor teardown
# 다시 상태 체크
sudo aa-status
1.2.3 iptables option
docker run -p port:port 또는 -P 옵션을 할때 docker는 iptables에서 해당 포트를 public으로 만듭니다.
이는 심지어 ufw default deny incoming 을 해도 ufw는 막지를 못합니다.
docker가 마음대로 iptalbes를 변경 못하도록 하기 위해서는 다음과 같이 옵션을 주면 됩니다.
sudo vi /etc/default/docker
DOCKER_OPTS = "--iptables=false"
iptalbes에서 확인해봅니다.
sudo iptables -L -n --line-numbers | grep 3306
1 ACCEPT tcp -- 0.0.0.0/0 172.17.0.2 tcp dpt:3306
다음과 같이 지울수 있습니다.
sudo iptables -D DOCKER 1
-D <체인이름> <헤더번호>헤더번호>체인이름>
1.2.4 Enable UFW forwarding
Docker 는 기본적으로 container networking을 하기 위해서 bridge를 사용합니다.
문제는 ufw 는 모든 forwarding traffic을 drop시켜버립니다. 따라서 ufw의 forwarding policy를 설정해주어야 합니다.
또한 외부 host에서 docker container에 접속하기 위해서는 2376포트를 열어주어야 합니다. 2376포트는 Docker의 기본 포트입니다.
sudo vi /etc/default/ufw
다음을 DROP에서 ACCEPT로 바꿔줍니다.
DEFAULT_FORWARD_POLICY="ACCEPT"
sudo ufw reload
sudo ufw allow 2375/tcp
1.2.5 Configure Docker to start on boot
sudo systemctl enable docker
1.2.6 Install Ubuntu Libraries
Docker 내부에서..
apt-get update
apt-get install -y sudo
apt-get install -y mercurial
apt-get install -y git
apt-get install -y python python-dev
apt-get install -y curl
apt-get install -y vim
apt-get install -y strace
apt-get install -y diffstat
apt-get install -y pkg-config
apt-get install -y cmake
apt-get install -y build-essential
apt-get install -y tcpdump
apt-get install -y screen
apt-get install -y man
apt-get install -y net-tools
apt-get install -y openssh-server
service ssh restart
2. Docker 101
2.1 Getting Started
docker info
docker pull ubuntu
Images 보기
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
centos 7 328edcd84f1b 5 weeks ago 193MB
실행중이거나 중단된 containers보기
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3032c49eb6a3 centos "/bin/bash" 11 seconds ago Up 10 seconds tender_morse
8142605eda66 centos "/bin/bash" 2 minutes ago Exited (0) 2 minutes ago centos
종료된 container 삭제시키기
$ docker rm 8142605eda66
2.2 Interactive Mode
--name [컨테이너 이름]
-i
,--interactive
--user [유저이름]
기본적으로 root 계정으로 로그인한다
docker run --name dev -it ubuntu:20.04 /bin/bash
실행중인 container에 접속은 다음과 같이 합니다.
# 먼저 daemon으로 계속 실행하는 container를 생성
docker run -d --name daemon_ubuntu -t ubuntu:20.04 /bin/bash
# 실행중인 container에서 명령어 실행
docker exec -it daemon_ubuntu /bin/bash
2.3 VIM Ansi Mode
Docker 에서 vi를 실행시킬때 이상현상이 일어난다면 다음과 vim에서 다음과 같은 명령어를 쳐줍니다.
또는 .vimrc 파일안에 넣어도 됩니다.
:set term=builtin_ansi
또는 다음과 같이 합니다.
:set nocompatible
2.4 Delete all containers
docker rm $(docker ps -a -q)
# 또는
docker container prune
2.5 Delete all images
docker rmi $(docker images -q)
2.6 Copy
Host File <–> Docker Container 복사하기
echo "Hello Anderson" > foo.txt
docker run -d --name mycontainer -t ubuntu:20.04 /bin/bash
docker cp foo.txt mycontainer:/foo.txt
docker exec -it mycontainer /bin/bash # 들어가서 ls, cat으로 확인
docker cp mycontainer:/foo.txt foo.txt
2.7 Commit
docker run을 하게 되면 실제로는 새로운 container를 생성하게 됩니다.
$ docker run -d --name test_commit -t ubuntu:20.04 /bin/bash
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e69589e2c14e ubuntu:20.04 "/bin/bash" 27 seconds ago Up 26 seconds test_commit
여기에서 CONTAINER ID를 잡아서 commit 시킵니다
docker commit test_commit andersonjo/test
2.8 Push
docker push andersonjo/test
만약 접속이 안되면 docker login
으로 해결.
잘됐으면 hub.docker.com 으로 들어가서 삭제 필요합니다.
- Docker Hub 접속
- 내 아이디: andersonjo
2.9 Attach
Local standard input, output, error streams 를 running container에 붙입니다.
즉 실행중인 docker container의 로그를 볼 수 있습니다.
docker run -d --name topdemo ubuntu /usr/bin/top -b
docker attach topdemo
2.10 Inspect & IP Address
docker inspect <CONTAINER NAME> | grep IPAddress
3. Dockerfile
3.1 Basic
Dockerfile 은 우선 FROM <이미지> 명령어부터 시작을 합니다.
`vi Dockerfile` 로 다음을 입력합니다.이미지>
FROM ubuntu:20.04
MAINTAINER Anderson Jo
USER root
WORKDIR ~/
RUN apt update
RUN apt install -y nginx
RUN echo "Hello Anderson!"
EXPOSE 22 80
CMD ["echo", "Hello! This is ANDERSON!"]
docker build -t [이미지 이름]
를 하면 새로운 이미지가 생성이 됩니다.
docker build -t myubuntu .
이후에 docker run myubuntu
로 “Hello! This is ANDERSON!” 확인합니다.
docker run -p 9876:80 -d -it myubuntu nginx -g "daemon off;"
이것로 daemon 띄워놓고 크롬에서 확인합니다.
-g "daemon off;"
옵션은 nginx만 실행하면.. daemon으로 실행되는게 이것을 막기 위함입니다.
4. Networks
4.1 Basic Networks
docker network ls
NETWORK ID NAME DRIVER
adcf91619326 bridge bridge
80360f12ec4e none null
15bd40f71d98 host host
위의 3가지 networks는 docker의 기본적인 네트워크입니다.
bridge 네트워크는 ifconfig를 치면 나오는 docker0 를 나타냅니다.
docker run –net=
ifconfig
docker0 Link encap:Ethernet HWaddr 02:42:d4:28:54:7e
inet addr:172.17.0.1 Bcast:0.0.0.0 Mask:255.255.0.0
inet6 addr: fe80::42:d4ff:fe28:547e/64 Scope:Link
UP BROADCAST MULTICAST MTU:1500 Metric:1
RX packets:23343 errors:0 dropped:0 overruns:0 frame:0
TX packets:36673 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:1502621 (1.5 MB) TX bytes:48796224 (48.7 MB)
만약에 docker run –net=none 으로 시작할 경우 해당 docker는 network를 할 수 없습니다.
inspect를 통해서 자세한 정보를 얻을수 있습니다.
docker network inspect bridge
5. User defined networks
새로운 bridge network 또는 overlay network를 만들어서 containers를 isolate하는데 사용할수 있습니다. 또한 network plugin 그리고 remote network를 만들수도 있습니다.
5.1 Bridge Network
docker network create --driver bridge isolated_nw
docker run --net=<NETWORK>
–net 을 통해서 해당 network를 사용하도록 할 수 있습니다.
동일한 network를 공유하는 containers들 끼리는 서로 network communication이 가능합니다.
single host안에 상대적으로 작은 network를 구성시 bridge network가 좋습니다. 하지만 매우 큰 networks를 구성해야 한다면 overlay를 사용하는것이 좋습니다.
overlay, plugin 등등의 내용은 아래의 링크를 참조
docker networks guide
SSH Service
docker run -d -P --user ubuntu --name dev -h docker -t andersonjo/ubuntu bash
-P 는 모든 container의 ports를 hosts에 엽니다. (반드시 대문자)
container에 들어가서 netstat으로 port가 열려있는지 확인해봅니다.
docker exec -it dev bash
netstat -tln
모든 ports가 열려 있는지 확인합니다.
docker inspect dev | grep PublishAllPorts
sudo apt-get install -y openssh-server
sudo service ssh restart
sudo sed -i 's/PermitRootLogin without-password/PermitRootLogin yes/' /etc/ssh/sshd_config
sudo sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/sshd
echo "export VISIBLE=now" >> ~/.profile
MariaDB
docker pull mariadb
docker run --name mariadb -p 3306:3306 -e MYSQL_ROOT_PASSWORD=1234 -d mariadb
docker exec -it mariadb bash
apt-get update
apt-get install vim
vi /etc/mysql/my.cnf
run실행할때 -p 3306:3306 이부분이 중요합니다.
실질적으로 host 에서 3306 port mapping 시켜줍니다.
[mysqld_safe]
default-character-set=utf8
[mysqld]
collation-server = utf8_unicode_ci
init-connect='SET NAMES utf8'
character-set-server = utf8
docker restart mariadb
mysql -h 172.17.0.2 -u root -p
6. UFW Port Forward
6.1 Check Port Forwarding
sudo vi /etc/default/ufw
DEFAULT_FORWARD_POLICY="ACCEPT"
sudo vi /etc/ufw/sysctl.conf
net.ipv4.ip_forward=1
net/ipv6/conf/default/forwarding=1
net/ipv6/conf/all/forwarding=1
6.2 NAT
NAT를 ufw의 configuration에 넣어줍니다.
filter rules 전에 다음의 설정을 넣어줍니다.
sudo vi /etc/ufw/before.rules
# NAT table rules
*nat
:POSTROUTING ACCEPT [0:0]
# Forward traffic through eth0 - Change to match you out-interface
-A POSTROUTING -s 192.168.1.0/24 -o eth0 -j MASQUERADE
# don't delete the 'COMMIT' line or these nat table rules won't
# be processed
COMMIT
sudo ufw disable && sudo ufw enable
6.3 Port Forwarding
# NAT table rules
*nat
:PREROUTING ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
# Port Forwardings
-A PREROUTING -i wlp2s0 -p tcp --dport 3306 --to-destination 172.17.0.1
# Forward traffic through eth0 - Change to match you out-interface
-A POSTROUTING -s 192.168.1.0/24 -o wlp2s0 -j MASQUERADE
# don't delete the 'COMMIT' line or these nat table rules won't
# be processed
COMMIT