애플리케이션을 개발하면서 운영체제에 필요한 여러 소프트웨어를 설치하는 작업은 번거롭고 까다로울 뿐 아니라 전문가가 설치한 것이 아니라면 실행에 문제가 생길 수 있다.
가상화의 필요성
이에 대한 해결책 중 하나로, 각각의 애플리케이션을 실행하기 위해 가상의 컴퓨터를 만들고 그 위에 운영체제를 설치한 후 필요한 소프트웨어를 실행하는 방법이 있다. 그러나 이러한 방식으로 가상 머신에 운영체제를 설치하면 용량이 크고 실행 속도가 느리며 호스트 컴퓨터 자체가 운영체제의 역할을 수행하는 등의 단점이 있다.
컨테이너 기술의 등장
리눅스 운영체제는 환상적인 앱 실행 방법을 제공하고 있는데, 이러한 혁신적인 기술이 *컨테이너 기술이다. 컨테이너 기술은 애플리케이션을 격리된 환경에서 실행하는 방식으로 앱 간의 간섭을 방지하고 효율적인 운영이 가능하다.
리눅스의 컨테이너 기술은 가상화 기술의 일종으로 앱을 실행하기 위해 필요한 라이브러리와 실행 파일만을 포함한 환경을 만들어낸다. 이 환경은 *호스트 운영체제와는 격리되어 있어 각 애플리케이션이 서로 영향을 미치지 않고 독립적으로 실행될 수 있다.
컨테이너 기술을 쉽게 활용할 수 있게 해주는 도구 중에서 가장 인기 있는 것이 도커(Docker)이다.
도커는 컨테이너 기술을 기반으로 하며, 하나의 호스트에서 각각의 애플리케이션을 격리된 환경에서 실행할 수 있다. 컨테이너는 각 애플리케이션을 실행하는데 필요한 라이브러리와 실행 파일이 포함되어 있다. 이미 존재하는 운영체제를 공유함으로써 설치 시간과 저장 용량을 절약할 수 있다.
*컨테이너: 호스트에서 격리된 각각의 실행 환경
*호스트: 운영체제가 설치된 컴퓨터
도커의 장점
도커는 사용이 간편하고, 배포 및 확장이 효율적이라는 점에서 많은 개발자와 기업에서 선호하는 도구이다. 도커를 사용하면 개발자는 각 애플리케이션을 컨테이너로 만들어 배포할 수 있다. 이로써 시스템의 일관성을 유지하고 여러 환경에서 동일한 애플리케이션을 실행할 수 있다. 또한 도커 허브(Docker Hub) 같은 온라인 저장소를 통해 이미지를 공유하고 관리할 수 있어, 협업과 배포 과정을 간편하게 만들어준다. 이로써 현대적인 애플리케이션 개발과 배포를 위한 필수 도구로 인정받고 있으며 도커의 사용범위는 계속해서 확장되고 있다.
도커 설치방법
docker.com - docs - download and install - docker esktop for mac 경로로 설치를 진행한다.
docker images
위의 명령어를 쳤을 때 에러가 뜨지 않으면 도커를 성공적으로 설치한 것이며 이제부터 도커를 명령어로 다룰 수 있다.
Image: Docker hub에서 찾은 필요한 소프트웨어를 컴퓨터에 다운로드 하는 것을 image라고 한다.
Container: image를 실행하는 것을 container라고 한다. 이미지도 여러 개의 컨테이너를 가질 수 있다.
Pull: 도커에서 이미지를 다운받는 행위를 pull이라고 한다.
Run: 이미지를 실행시키는 행위를 run이라고 한다. run을 하면 이미지가 컨테이너가 되고 컨테이너가 실행되면서 컨테이너 안에 포함되어 있는 프로그램이 실행되면서 그 프로그램을 사용할 수 있게 된다.
도커 허브(Docker hub)에서 필요한 이미지 다운로드 받는 방법
hub.docker.com - Explore - containers - 원하는 소프트웨어가 있는 컨테이너를 다운로드 받을 수 있다.
search: httpd official image
docker pull httpd
메뉴얼 참고
docs.docker.com - reference - command line reference - docker cli - docker pull
docker images 명령어를 통해 httpd가 잘 다운로드 됐는지 확인할 수 있다.
이미지를 실행시켜 컨테이너를 만들고 실행하는 방법
docker run httpd
컨테이너를 보고 싶을 때
docker ps
이미지를 실행시킬 때 여러개의 컨테이너를 만들 수 있음
컨테이너 이름 : wsl2로 설정
docker run --name ws2 httpd
GUI로 실행하는 방법
도커 데시보드에서 run 클릭
Container name 입력 후 Run 클릭
실행중인 컨테이너를 끄고 싶다.
docker stop ws2
컨테이너 네임 또는 컨테이너 아이디를 적으면 된다.
실행되고 있던 컨테이너가 꺼진 것을 확인할 수 있다.
docker ps일 했을 때는 보이지 않으니 -a 옵션을 통해 확인할 수 있다. 컨테이너가 삭제되진 않았다.
docker ps -a
꺼진 컨테이너를 다시 시작하고 싶다면
docker start ws2
도커 로그 확인
docker logs ws2
실시간 로그를 확인하고 싶다면
docker logs -f ws2
컨테이너 삭제
docker rm ws2
현재 실행중인 컨테이너는 바로 지울 수 없기 때문에 아래와 같은 에러가 뜬다.
Error response from daemon: You cannot remove a running container 60d44eb46eadc5dd9223a9b2c5cff86433e8f421c86bbd9701003be813e14c26. Stop the container before attempting removal or force remove
명령어 docker stop ws2 후에 docker rm ws2 를 하면 삭제된다.
강제 삭제
docker rm --force [names]
이미지 삭제
docker rmi httpd
도커를 동작하는 많은 소프트웨어들이 네트워크 위에서 동작한다.
도커를 이용하면 웹서버가 컨테이너에 설치된다.
컨테이너가 설치된 운영체제를 도커 호스트(Docker host) 라고 부른다.
하나의 호스트에는 여러 개의 컨테이너를 만들 수 있다.
컨테이너와 호스트 모두 독립적인 실행 환경이기 때문에 각자 독립적인 포트와 파일 시스템을 가지고 있으므로,
호스트의 80번 포트와 컨테이너의 80번 포트를 연결해주면 된다.
컨테이너 실행 방법을 이렇게 바꾼다.
docker run -p 80:80 httpd
호스트의 80번으로 들어온 신호가 컨테이너의 80번 포트로 전송되는 것이다.
이렇게 연결된 포트로 신호를 전달하는 것을 포트 포워딩(Port forwarding)이라고 한다.
다운로드
docker pull httpd
도커 이미지에서 컨테이너를 실행
docker run --name ws3 -p 8081:80 httpd
8081 → 80번으로 보낸다.
주소를 통해 접속할 때 컨테이너 안에 있는 웹서버가 그 안에 저장되어 있는 index.html 파일을 읽어서 보여주고 있는 화면이다.
접속하면 reload 할 때마다 접속이 됐다는 뜻에서 로그가 찍히는 것을 확인할 수 있다.
이렇게 httpd 라고 하는 애플리케이션을 실행할 수 있는 상태가 된 것이다!
index.html 파일을 편집해서 웹 서버를 이용해보자
그러기 위해선 컨테이너 안으로 들어가서 컨테이너를 수정할 수 있어야 한다.
docker exec ws3 pwd
컨테이너를 대상으로 실행하는 명령어 pwd, ls
컨테이너와 지속적으로 연결을 유지하면서 명령을 전달하고 싶을 때
docker exec -it ws1 /bin/sh
shell이라고 불리는 프로그램은 사용자가 입력한 명령을 shell 프로그램이 받아서 그것을 운영체제에 전달하는 창구같은 역할을 한다.
#이 나오면 지금부터 내리는 명령은 ws1 컨테이너를 대상으로 내려지는 명령이다.
이 연결을 끊고 컨테이너 밖으로 나가고 싶다. host를 대상으로 하는 명령어
# exit
Tip.
sh는 기능이 부족해 bash shell을 많이 쓴다.
docker exec -it ws1 /bin/bash
이제 인덱스 파일을 수정해보자.
hub.docker.com에 들어가서 보면
이 경로에 사용자가 요청한 웹페이지를 보관하도록 약속되어 있다.
메뉴얼처럼 경로로 이동
# cd /usr/local/apache2/htdocs/
# ls -al
파일을 조회해보니 index.html 가 있다.
컨테이너는 용량이 작기 때문에 atp나 yum를 이용해서 nano나 vim을 설치하면 된다.
# apt install nano
설치 중 아래와 같은 오류가 뜬다면 apt를 업데이트하고 다시 nano를 설치하면 된다.
E: Package 'nano' has no installation candidate
# apt update
apt 패키지 매니저가 사용하는 패키지 저장소(repository)에 nano가 포함되어 있지 않거나 저장소를 업데이트하지 않아서 오류가 발생할 수 있다.
# nano index.html
명령어를 치면 index.html을 편집할 수 있다.
편집 후 ^X → Y → Enter를 누르면 완료!
컨테이너 안의 파일을 바꿀 수 있는 상태가 되었다!
그러나 이 상태에서 위험한 상황이 발생할 수 있다.
index.html 파일을 수정했는데 컨테이너가 사라졌다면?
우리가 컨테이너를 사용하는 이유는 필요에 따라 언제든지 생성하고 삭제하는 것이다.
컨테이너의 usr/local/apache2/htdocs/ 디렉토리와 host의 htdocs의 디렉토리를 연결하고 호스트 쪽에서 수정이 이루어졌을 때 그것이 컨테이너의 파일시스템에 반영될 수 있다면 컨테이너가 날아가도 우리의 소스코드는 여전히 호스트에 남아있기 때문에 보다 안전하게 개발할 수 있고 버전관리도 쉽다.
실행환경은 컨테이너에게 맡기고 파일을 수정하는 작업은 호스트에서 진행하는 방법에 대해 알아보자
desktop에 폴더 생성 후 index.html 파일 입력
docker run -p 9999:80 -v ~/Desktop/htdocs:/usr/local/apache2/htdocs/ httpd
-p: 이 옵션은 호스트의 포트를 컨테이너의 포트로 매핑하는 역할을 한다. 여기서는 호스트의 9999번 포트를 컨테이너의 80번 포트로 매핑하고 있다. 이렇게 함으로써 호스트의 9999번 포트를 통해 컨테이너 내의 웹 서버에 접근할 수 있게 된다.
-v: 이 옵션은 호스트의 디렉토리를 컨테이너의 디렉토리로 볼륨 마운트하는 역할을 한다. 여기서는 호스트의 ~/Desktop/htdocs 디렉토리를 컨테이너의 /usr/local/apache2/htdocs/ 디렉토리로 연결하고 있다. 이렇게 함으로써 호스트에서 해당 디렉토리의 파일을 수정하면 컨테이너 내의 웹 서버에 반영되게 된다.
파일의 내용을 수정하면
호스트와 연결되어 있는 컨테이너 안의 파일시스템도 반영된다.
호스트에서 파일이 수정되고 노출되기 때문에 호스트 환경 안에서 이 파일 안의 버전 관리나 코드 수정 등의 작업이 가능해진다.
도커 컴포즈(Docker compose)
여러 개의 도커 컨테이너를 연결하여 하나의 애플리케이션을 실행하는 경우 그 관리를 쉽게 하기 위해 도커 컴포즈(Docker Compose)를 사용할 수 있다. Docker Compose는 여러 컨테이너로 이루어진 복잡한 애플리케이션을 정의하고 실행하는 도구이다.
도커 컨테이너를 만드는 명령어, 컨테이너를 만들 때마다 실행해야 한다면 얼마나 귀찮을까?
docker-compose.yml 파일을 사용하여 WordPress와 MySQL 컨테이너를 정의할 수 있다.
docker-compose up
이 명령어를 실행하면 docker-compose.yml 파일에 정의된 서비스들이 시작된다.
WordPress 컨테이너와 MYSQL 컨테이너를 만들어 연결시키면 web browswe에서 WordPress에 접속하면 WordPress가 MYSQL에 접속해서 여러가지 작업을 하고 그 결과를 가져온 다음에 웹브라우저에게 보내게 해준다.
이런 시나리오의 환경을 Docker compose를 활용해 만들 수 있는 것이다.
command를 실행하는 명령어
docker network create wordpress_net
db라는 이름의 MYSQL 이미지를 기반으로 컨테이너를 만드는 run 명령어 실행
docker \
run \
--name app \
-v "$(pwd)/app_data:/var/lib/mysql" \
-e "MYSQL_ROOT_PASSWORD=123456" \
-e "MYSQL_DATABASE=wordpress" \
-e "MYSQL_USER=wordpress_user" \
-e "MYSQL_PASSWORD=123456" \
--network wordpress_net \ #이 컨테이너가 네트워크에 연결됨
mysql:5.7
호스트에 db_data라는 폴더가 생성된다.
MYSQL의 데이터가 저장되는 파일이 저 곳에 저장됨, 덕분에 데이터베이스를 껐다가 다시 킬 때 실제로 데이터가 저장되는 db_data는 온전히 보존되어 있기 때문에 컨테이너를 껐다 켜도 데이터를 유지할 수 있다.
wordpress 컨테이너를 실행하는 명령어
docker \
run \
--name app \
-v "$(pwd)/app_data:/var/www/html" \
-e "WORDPRESS_DB_HOST=db" \
-e "WORDPRESS_DB_USER=wordpress_user" \
-e "WORDPRESS_DB_NAME=wordpress" \
-e "WORDPRESS_DB_PASSWORD=123456" \
-e "WORDPRESS_DEBUG=1" \
-p 8080:80 \
--network wordpress_net \
wordpress:latest #워드프레이스 최신 버전이 컨테이너로 만들어짐
두 개의 컨테이너는 wordpress_net이라는 네트워크에 연결된 상태이다.
wordpress도 파일을 host에 카피한 것을 확인할 수 있다.
-e "WORDPRESS_DB_HOST=db" \
워드프레스 입장에서 데이터베이스에 접속할 때 db의 주소를 호스트에다 지정하는데
컨테이너의 이름인 db를 적으면 접속이 가능하다면 얼마나 편할까?
그걸 하려면 network를 만들어야 한다. → docker network create wordpress-net
도커컴포즈에서는 네트워크를 만들고 연결하는 작업이 필요없음
도커컴포즈를 만드는 순간 자동으로 네트워크가 만들어지고 생성한 컨테이너에 자동으로 연결이 되기 때문이다.
localhost:8080 에 접속하면
wordpress를 설치하는 화면이 나온다.
continue를 누르면 wordpress가 생성된다.
이렇게 복잡한 명령을 기억하긴 쉽지 않다.
docker-compose up
명령어를 치면 이것이 실행될 수 있도록 하는 실행파일이 준비되어 있다.
기존의 생성한 컨테이너를 지우고 다시 해보자
docker rm --force app
docker rm --force db
docker network rm wordpress_net
생성된 폴더들(app_data, db_data)도 지운다.
docker-compose.yml 파일을 만들고 해당 코드를 입력한다.
version: "3.7"
services:
db:
image: mysql:5.7
volumes:
- ./db_data:/var/lib/mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: root_password #설정한 DB 비밀번호 입력
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress_user
MYSQL_PASSWORD: root_password #설정한 DB 비밀번호 입력
app:
depends_on: #db컨테이너가 만들어지고 워드프레스 컨테이너가 만들어지게 함
- db
image: wordpress:latest
volumes:
- ./app_data:/var/www/html
ports:
- "8080:80"
restart: always
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_NAME: wordpress
WORDPRESS_DB_USER: wordpress_user
WORDPRESS_DB_PASSWORD: root_password #설정한 DB 비밀번호 입력
root_password에는 내가 설정한 비밀번호 입력한다.
이렇게 MySQL 데이터베이스 컨테이너(db)와 워드프레스 애플리케이션 컨테이너(app)를 만들었다.
외부에서 접속하기 위해 워드프레스 컨테이너(app)에는 접근을 허용하고 보안상의 이유로 MySQL 컨테이너(db)에는 접근을 제한한다.
호스트의 8080번 포트를 app 컨테이너의 80번 포트에 매핑함으로써 워드프레스 애플리케이션에 대한 외부 액세스를 허용하면서 MySQL 데이터베이스 컨테이너를 격리시킨다.
그래서 app 컨테이너의 80번 포트와 호스트의 8080포트를 연결시켜서 8080에 접속하면 80번에서 리스닝하고 있는 웹 서버가 접속될 수 있게 한다.
기존에는 -p 옵션을 사용해서 호스트 포트를 컨테이너 포트로 매핑했다면 도커컴포즈에서는 위와 같이 ports: 에 포트번호를 쓰면 된다.
docker-compose up
localhost:8080 에 접속해보면 이번에도 wordpress 설치화면이 실행되는 것을 확인할 수 있다.
컨테이너 실행 종료
docker-compose down
실행한 컨테이너들을 종료한다.
이 글은 생활코딩에서 배운 내용을 바탕으로 작성되었다.
취업 준비를 하면서 Docker의 중요성을 깨닫고 생활코딩 강의를 통해 도커와 도커 컴포즈의 기본 개념과 활용법을 알 수 있는 기회였다.
생활코딩은 항상 새로운 지식을 습득하는 과정에서 쉽게 따라갈 수 있도록 도움을 준다. 덕분에 도커의 전체적인 흐름을 파악하고 실제 프로젝트에 적용할 수 있는 자신감을 얻었다💪😉
'Services > Tool' 카테고리의 다른 글
[Eclipse] 이클립스에 코틀린 셋팅하기 (0) | 2024.05.02 |
---|---|
[Eclipse] 이클립스 설치하기(for macOS) (0) | 2024.05.02 |
[Eclipse] 이클립스 버전 업데이트 (0) | 2024.05.02 |
[Supabase] Local 개발환경 셋팅 (0) | 2023.10.06 |
[MySQL] 윈도우 실행 명령어 + JOIN을 활용한 문제 풀이(westagram) (0) | 2023.08.06 |