Docker 환경에 Service 및 Application을 구동시키 위한 전체적인 과정은 다음과 같습니다.
![](https://miro.medium.com/v2/resize:fit:385/1*f5PKsp4w-9VQViY3X6LhMA.png)
지금까지는, Docker Registry(Docker Hub)에 배포되어 있는 있는 Image를 이용해 Container를 구동시켰습니다. 이제부터는 위에서 정리한 과정대로, Dockerfile로 Image를 생성하고 다른 Machine에서 배포된 Image로 Container를 실행시켜 보겠습니다.
![](https://miro.medium.com/v2/resize:fit:506/1*1EhEMmB0Y5S5JsnmxilIcA.png)
신규 Image 생성에서 배포까지
Dockerfile 작성
image-build-test 폴더를 생성한 뒤, 다음의 내용이 포함된 Dockerfile을 생성합니다.
![](https://miro.medium.com/v2/resize:fit:175/1*evT-Gmt23bUF7o07KHiiQQ.png)
image-build-test 폴더의 내부 구조는 다음과 같습니다.
![](https://miro.medium.com/v2/resize:fit:251/1*LaZ6Kj0l0Y6-hAHLuMG_hA.png)
Image Build
image-build-test 폴더 내에서 생성한 Dockerfile로 ${username}/my-base-image:1.0
이란 이름의 Image를 Build합니다.
![](https://miro.medium.com/v2/resize:fit:469/1*H5XlaIoifqhBbBPZy8t5uA.png)
![](https://miro.medium.com/v2/resize:fit:700/1*qrf1mbfhWwzglCRYAcZm6A.png)
처음 Image를 Build하게 되면, Local Instance에 저장된 Base Image(여기서는 Ubuntu Image입니다)가 존재하지 않기 때문에, Docker Registry(Docker Hub)로부터 Pull을 받습니다. 그 후, Dockerfile의 COPY명령어가 새로운 Layer로 생성되고, ${username}/my-base-image:1.0
Image가 Build됩니다.
생성된 Image를 확인해 보겠습니다.
![](https://miro.medium.com/v2/resize:fit:700/1*TJKzB78pMkHZ8BBCxbxWBg.png)
Container를 Run
방금 생성한 Image를 Local에서 실행시켜 보겠습니다. 정상적으로 실행된다면, 아래와 같이 Container ID가 나타나고 docker ps
로 실행중인 해당 Container를 목록에서 확인할 수 있습니다.
![](https://miro.medium.com/v2/resize:fit:700/1*ZGkEbCICwsUEPW2PbVxHJg.png)
Image를 Docker Hub에 배포
이제는 생성한 Image를 Docker Registry에 배포해 보겠습니다. 따로, Docker Registry를 구성하지 않았기 때문에 배포되는 장소는 Docker Hub이며, 정상적으로 배포하기 위해서 먼저 Login을 하겠습니다.
![](https://miro.medium.com/v2/resize:fit:700/1*uo5doYd4_DQVjdX7f0uLDg.png)
로그인이 정상적으로 되었다면 docker push
로 생성한 Image를 Docker Registry에 등록하겠습니다.
![](https://miro.medium.com/v2/resize:fit:700/1*cgXjxPV6NyaDgcMD7GYa2A.png)
Console에 찍힌 로그를 보면, Unbuntu Image는 이미 Docker Registry에 존재하기 때문에 Mount만 되고, 그 외에 생성한 Layer만 추가로 Push되는 것을 볼 수 있습니다.
![](https://miro.medium.com/v2/resize:fit:399/1*NmfSG9gHia3vrrgozkTfQA.png)
Hello World를 만들어 보자
처음에 hello-world
를 실행시켜 봤었습니다. 지금부터는 직접 구현해 보겠습니다.
Dockerfile 변경
기 생성된 Dockerfile을 Dockerfile.base로 변경 한 후, ${username}/my-base-image:1.0
Image에 CMD
Layer가 추가된 Image를 생성하는 Dockerfile을 새로 생성합니다.
![](https://miro.medium.com/v2/resize:fit:340/1*uarWkFb-R2xKXt6ew5gq0w.png)
다음과 같은 내용으로 hello.sh를 생성합니다.
![](https://miro.medium.com/v2/resize:fit:184/1*sbmYeBVPuO2OVVEVcusxTw.png)
hello.sh 파일을 저장하고 실행가능한 상태로 변경합니다.
![](https://miro.medium.com/v2/resize:fit:364/1*rBtCY8xNgYwvyHW4L0_aFg.png)
변경된 폴더 구조는 다음과 같습니다.
![](https://miro.medium.com/v2/resize:fit:248/1*BVsCBIlHeRSareXiPvrZnA.png)
Hello World Image Build
변경된 Dockerfile로 ${username}/my-final-image:1.0
이란 이름의 Image를 Build합니다.
![](https://miro.medium.com/v2/resize:fit:700/1*EHTXz6Vw7iVjGJmwoEr1lA.png)
처음에 Build했을 때 보다는 월등히 빠르게 Build되는 것을 알 수 있습니다. ${username}/my-final-image:1.0
의 Base Image가 이미 Local에 존재하기 때문에 CMD
에 해당하는 Layer만 생성하면 되기 때문입니다.
생성된 Image를 확인합니다.
![](https://miro.medium.com/v2/resize:fit:700/1*PGmWyFwnnCA3KA4U9oSnrw.png)
docker history [OPTIONS] IMAGE
로 각 Image를 구성하는 Layer를 한번 확인해 보겠습니다. 두 Image 사이에서 공유하는 Layer는 암호화된 ID가 동일하다는 것을 확인할 수 있습니다.
${username}/my-base-image:1.0
![](https://miro.medium.com/v2/resize:fit:700/1*YNI5T8Xo7bdiPE0v7N1-aA.png)
${username}/my-final-image:1.0
![](https://miro.medium.com/v2/resize:fit:700/1*BTUsJcu66u3ApZImHqhgYA.png)
다시 Push
${username}/my-final-image:1.0
Image를 Docker Registry에 Push합니다. Docker Registry에는 ${username}/my-base-image:1.0 Image의 Layer들이 이미 존재하고 있기 때문에, 추가된 Layer(Dockerfile에 추가된 CMD
)만 Push됩니다.
![](https://miro.medium.com/v2/resize:fit:700/1*edtRDFTPyl7OomcSKX5iHw.png)
다른 곳에서 Hello World를 실행해보자
새로운 환경에서 지금 만든 Image를 Container로 실행시켜 보겠습니다. 그 전에 docker-machine create
로 새로운 Docker 환경을 구성하겠습니다.
![](https://miro.medium.com/v2/resize:fit:700/1*VyBPQZ0fCnqZ-iEQKGjz9A.png)
새로 구성한 Docker 환경에 docker-machine ssh
로 접속하겠습니다.
![](https://miro.medium.com/v2/resize:fit:700/1*cOz-vCK9LfOx2KpUFyHFGg.png)
지금 만든 Image를 Pull받고,..
![](https://miro.medium.com/v2/resize:fit:700/1*C_9uyDPvlf2tVEPRN2exXw.png)
새로 구성된 환경이라 Image의 모든 Layer들을 내려받습니다. 그리고, docker run
을 실행하면 !!!
![](https://miro.medium.com/v2/resize:fit:620/1*eUPOfiJujlZRiHK8P0jWpA.png)
처음에 정리했던 Build — Push — Pull — Run의 과정으로 Container가 실행되는 것을 확인할 수 있었습니다. Docker Engine이 설치된 어떤 환경에서도 지금 만든 Hello world는 실행될 것입니다. 여기서 더 나아가 Hello world는 다양한 메시지를 입력받거나 혹은, 저장되어 있는 메시지들을 출력하는 Application으로 발전할 수도 있습니다. 그렇다면, 이 Application의 기능이 Upgrade되어, 새로운 버전의 Image를 만들고 새로운 Container를 기동시켜야 한다면, 변경된 내용(입력받거나 혹은 저장된 메시지들)들은 어떻게 될까요?
우리는 이전에 Image와 Container의 Layer 구조를 살펴보면서, 해당 Container에 읽기/쓰기가 가능한 Layer내에 변경된 내용들이 저장된다는 것을 알고 있습니다. 그리고, 이 데이터들은 해당 Container와 같이 소멸된다는 것도 알고 있습니다. 그럼, Container가 소멸되었다가 새로 생성되어도, 이전의 데이터들을 유지하여 사용할 방법은 없을까요? 이 다음에는 Docker의 Volume을 이용하여, 데이터를 보존하는 방법에 대해서 확인해볼 필요가 있겠네요.