컨테이너와 호스트(도커 엔진을 실행 중인 PC) 사이에 파일을 복사하는 방법을 배운다.
소프트웨어의 개입 없이 서버와 로컬 컴퓨터 간에 파일을 주고 받아야 할 때가 있다.
파일 복사는 컨테이너 → 호스트 , 호스트 → 컨테이너로 양방향 모두 가능하다.
docker cp 호스트_경로 //호스트 -> 컨테이너
docker cp 컨테이너_이름:컨테이너_경로 // 컨테이너 -> 호스트
<html>
<meta charset="utf-8"/>
<body>
<div>안녕하세요!</div>
</body>
</html>
메모장에서는 파일 형식에서 “모든 파일”을 선택한 후 파일 이름을 “index.html”로 지정해 저장하면, .html 확장자가 적용된다.
단계 0 : 아파치 컨테이너 생성
docker run --name apa000ex19 -d -p 8089:80 httpd
단계 1 : 웹 브라우저를 통해 아파치에 접근해 초기 화면 확인
http://localhost:8089/ 에 접근해 아파치 초기 화면을 확인한다.
단계 2: cp 커맨드를 실행해 호스트에서 컨테이너로 파일을 복사
docker cp C:\Users\minyeob\Desktop\index.html apa000ex19:/usr/local/apache2/htdocs/
다음과 같이 “copying between containers is not supported” error가 뜬다
git bash 가 아닌 cmd 창에서 명령어를 입력하니 해결되었다..
단계 3: 아파치의 초기 화면이 index.html 파일의 내용으로 바뀐 것을 확인
호스트에 있던 index.html 파일을 index2.html로 이름 바꾸고 진행
단계 0 : 아파치 컨테이너 생성
단계 1 : cp 커맨드를 실행해 컨테이너에서 호스트로 파일을 복사
docker cp apa000ex19:/usr/local/apache2/htdocs/index.html C:\Users\minyeob\Desktop\
단계 2 : 호스트에 index.html 파일이 잘 복사됐는지 확인
볼륨을 마운트하면 컨테이너의 일부를 호스트 컴퓨터의 일부와 같이 다룰 수 있어 편리하다.
볼륨 : 스토리지의 한 영역을 분할한 것을 말한다 (카스테라를 자른 한 조각이라고 생각 하면 된다)
마운트 : 연결하다 라는 의미 그대로 대상을 연결해 운영체제 또는 소프트웨어의 관리하에 두는 일을 말한다. (USB 메모리를 컴퓨터에 마운트)
컨테이너는 생성 및 폐기가 매우 빈번하기 때문에 매번 데이터를 옮기는 대신 처음부터 컨테이너 외부에 둔 데이터에 접근해 사용하는 것이 일반적이다.(데이터 퍼시스턴시) 이때 데이터를 두는 장소가 마운트 된 스토리지 영역이다.
볼륨 마운트
: 도커 엔진이 관리하는 영역 내에 만들어진 볼륨을 컨테이너에 디스크 형태로 마운트한다, 직접 조작하기 어려우므로 ‘임시 목적’ 파일을 두는 목적으로 많이 사용`
바인드 마운트
: 도커가 설치된 컴퓨터의 문서 폴더 또는 바탕화면 폴더 등 도커 엔진에서 관리하지 않는 영역의 기존 디렉터리를 컨테이너에 마운트 하는 방식이다. 자주 사용하는 파일을 두는 데 사용 한다.
파일을 직접 편집해야 할 일이 많다면 바인드 마운트 사용
그렇지 않다면 볼륨 마운트를 사용
항목 | 볼륨 마운트 | 바인드 마운트 |
---|---|---|
스토리지 영역 | 볼륨 | 디렉터리 또는 파일 |
물리적 위치 | 도커 엔진의 관리 영역 | 어디든지 가능 |
마운트 절차 | 볼륨을 생성 한 후 마운트 | 기존 파일 또는 폴더를 마운트 |
내용 편집 | 도커 컨테이너를 통해서 | 일반적인 파일과 같이 |
백업 | 절차가 복잡함 | 일반적인 파일과 같이 |
절차 : 스토리지 영역을 생성 → 컨테이너를 생성( 및 마운트)
스토리지 영역을 만드는 방법
docker volume create 볼륨_이름 // 볼륨 마운트
docker volume rm 볼륨_이름 // 볼륨 삭제
스토리지를 마운트 하는 커맨드
docker run (생략) -v 스토리지_실제_경로:컨테이너_마운트_경로 (생략) // 바인드 마운트 커맨드
docker run (생략) -v 볼륨_이름:컨테이너_마운트_경로 (생략) // 볼륨 마운트 커맨드
apa_folder라는 이름으로 마운트 원본이 될 폴더/디렉터리를 생성한다
아파치 이미지(httpd)를 사용해 apa000ex20 이라는 이름으로 컨테이너를 생성 및 실행
docker run --name apa000ex20 -d -p 8090:80 -v C:\Users\minyeob\Desktop\apa_folder:/usr/local/apache2/htdocs httpd
docker volume create apa000vol1
docker run --name apa000ex21 -d -p 8091:80 -v apa000vol1:/usr/local/apache2/htdocs httpd
docker volume inspect apa000vol1
docker container inspect apa000ex21
볼륨 자체를 복사할 수 없으므로 볼륨을 확인할 때처럼 별도의 리눅스 컨테이너를 연결해 볼륨의 내용을 압축해 저장한다 컨테이너 생성(run) 과 함께 tar 명령어로 백업을 수행
docker run --rm -v 볼륨명:/moto -v 백업_저장_폴더명:/target busybox tar cvzf /sake/백업파일이름.tar.gz -C /source .
run 커맨드로 리눅스 운영체제(busybox) 컨테이너를 실행하고 실행 후 바로 삭제할 예정이므로 옵션에 —rm 을 추가
(-v 백업저장폴더:/target )
/source의 내용을 /target 안의 ‘백업파일명.tar.gz’로 압축해 저장하라는 의미다.
나만의 이미지를 만들어 똑같은 구성의 컨테이너를 대량으로 만들 수 있고, 다른 컴퓨터 또는 서버세 이동 시킬 수도 있다.
방법 2가지
commit 커맨드로 기존 컨테이너를 이미지로 변환
docker commit 컨테이너_이름 새로운_이미지_이름
Dockerfile 스크립트로 이미지를 만드는 방법
docker build -t 생성할_이미지_이름 재료_폴더_경로
docker run --name apa000ex22 -d -p 8092:80 httpd
docker commit apa000ex22 ex22_original1
apa_folder 안에 index.html 파일을 배치한다
파일 이름은 확장자 없이 Dockerfile 이라고 붙이고 apa_folder에 저장한다.
FROM httpd
COPY index.html /usr/local/apache2/htdocs
docker build -t ex22_original2 C:\Users\minyeob\Desktop\apa_folder
다음과 같은 Error 발생..
메모장으로 만들었을때의 확장명이 .txt 로 되어있었는데 그것이 숨겨져있었기 때문이다
보기 → 옵션 → 폴더 및 검색 옵션 변경 →
보기 → 알려진 파일 형식의 파일 확장명 숨기기 체크 해제 후에
.txt 확장자를 지워주면 해결!!
빌드가 잘 된 모습
도커를 실제 운용하는 현장에서는
사내에서 개발한 시스템을 운영하는 경우가 많다.
사내 개발 시스템이 아니더라도 공식 배포되는 소프트웨어 역시 수정해야 할 필요가 종종 있는데,
큰 수정은 아니더라도 설정 파일을 매번 작성하기는 귀찮기 때문이다.
컨테이너를 개조하는 방법에는 두 가지 방법이 있다.
첫번째는 이전에 배운 파일 복사와 마운트를 이용한 방법이고,
두번째는 컨테이너에서 리눅스 명령어를 실행하는 방법이다.
컨테이너에서 리눅스 명령어를 실행하기 위해서는 리눅스에 우리의 명령을 전달해 주는 프로그램인 셸(shell) 이 필요하다.
셸에도 여러 종류가 있지만, 대부분의 컨테이너에서 가장 일반적으로 사용되는
bash
를 기준으로 설명
컨테이너를 아무 설정 없이 실행하면 bash
가 동작하지 않는 상태로 실행되기 때문에,
bash
를 실행해 우리의 명령을 입력받을 수 있는 상태로 만들어야 한다.
/bin/bash
➡️ 이 인자는 docekr run
또는 docker exec
커맨드와 함께 사용한다.
docker exec
& docker run
docker exec
는 컨테이너 속에서 명령어를 실행하는 커맨드이다.
실행 중인 컨테이너에 run
커맨드를 사용할 수는 없으므로 이 방법을 사용한다.
이 방법으로 bash
없이 어느 정도 명령을 직접 전달할 수는 있지만 초기 설정이 없어 동작하지 않는 경우도 있기 때문에 기본적으로는 셸을 통해 명령을 실행한다.
만약 docker run
커맨드에 인자를 붙였다면 상황이 조금 복잡해진다.
이 경우에는 컨테이너에 들어있는 소프트웨어를 실행하는 대신 bash
가 실행되기 때문에,
컨테이너는 실행 중인데 소프웨어는 실행 중이 아닌 상태가 된다.
exec
커맨드에 인자를 추가한 예➡️ docker exec [옵션] [컨테이너_이름] /bin/bash
run
커맨드에 인자를 추가한 예➡️ docker run [옵션] [이미지_이름] /bin/bash
예를 들어, 아파치 컨테이너의 이름이 apa000ex23
이고 이 컨테이너의 bash
인자를 추가하려면 다음과 같이 하면 된다.
exec
커맨드➡️ docker exec -it apa000ex23 /bin/bash
run
커맨드➡️ docker run --name apa000ex23 -it -p 8089:80 httpd /bin/bash
(이 경우 아파치가 실행되지 않음)bash
가 실행되면 셸에 입력된 명령은 도커 엔진이 아닌 해당 컨테이너로 전달되는 것에 유의해야 한다.
도커 컨테이너와 도커 엔진은 별개의 존재이므로 bash
를 통해 컨테이너 내부를 조작하는 동안에는 도커 명령을 사용할 수 없다.
정리하자면
컨테이너를 만들고 삭제하거나 컨테이너 자체에 대한 명령은 도커 엔진을 통하는 것이고,
컨테이너 내부를 다루는 명령은 bash
를 통하는 것 이다.
그러므로 컨테이너 안에서 할 일을 마쳤다면, exit
명령어를 통해 다시 컨테이너에서 나와야 한다.
컨테이너 안에서 실행해야 하는 명령과 도커 엔진을 통해야 하는 명령에는 어떤 차이가 있는지 간단히 정리해 보겠다.
도커 엔진을 통해야 하는 명령
컨테이너 내부에서 실행하는 명령
앞에서 설명했듯 도커와 컨테이너는 별개의 존재이므로 상황에 따라 사용하는 언어가 달라지기도 한다.
컨테이너에 들어있는 '운영체제 비슷한 것' 의 종류가 무엇이냐에 따라 컨테이너 내부에서 사용하는 명령어가 달라지게 된다.
다시 말해 컨테이너A가 데비안 계열, 컨테이너B가 레드햇 계열을 사용한다면
똑같이 도커에서 실행 중인 컨테이너라도 컨테이너 내부에서 사용하는 명령의 스타일이 달라진다.