[#4] Docker Hub 에 레포지토리 업로드하기!

Written by 코드팩토리 JC

1월 15, 2024

코드팩토리 Docker 부터 Kubernetes 까지

소개

이번 회에선 로컬 시스템에서 빌드 한 Docker 컨테이너를 Docker Hub로 업로드하는 작업을 하고 태그에 대해 자세히 알아보도록 하겠습니다.

로컬 시스템에 존재하는 이미지 리스팅 하기

외부 레포지토리에서 Pull을 해와서 로컬에 시스템에 캐싱이 되어있거나 로컬 시스템에서 커스텀 이미지를 빌드 한 경우 아래 커맨드를 사용해서 현재 로컬 시스템에 존재하는 모든 이미지들을 리스팅 해볼 수 있습니다.

docker image ls
ShellScript

실행이 되면 아래와 비슷한 결괏값을 받아볼 수 있습니다.

docker image ls
docker image ls

저는 여러 이미지들이 캐싱 되어 있기 때문에 여러 개의 이미지가 리스팅 되지만 중요한 건 저희가 전 회에서 빌드 한 nodejs-docker 이미지입니다. REPOSITORY, IMAGE ID, CREATED, SIZE는 이해하기 쉽지만 TAG의 경우 이미지를 빌드 할 때 latest라는 단어를 쓰지 않았음에도 불구하고 latest라는 태그가 설정되어 있는 걸 볼 수 있습니다. 전 회에서 nodejs-docker 이미지를 빌드 할 때 저희는 사실 TAG는 설정하지 않고 nodejs-docker라는 레포지토리 이름만 설정을 하였는데 그럴 경우 자동으로 Docker에서 latest라는 태그를 붙여줍니다.

Docker Hub 설정하기

레포지토리를 다른 시스템과 공유하거나 Docker를 사용해서 리모트 레포지토리에서 Pull 해오는 걸 가능하게 하려면 수많은 컨테이너 레포지토리중 하나에 이미지를 업로드해야 합니다. 컨테이너 레포 히토리는 각각 클라우드 회사마다 하나씩 있고 (AWS, GCP, Azure) 저희가 사용한 공식 nodeJS 이미지를 포함한 가장 많은 퍼블릭 레포지토리들이 호스팅 되어있는 Docker Hub가 있습니다. Docker Hub의 경우 퍼블릭 레포지토리들은 모두 무료이고 프라이빗 레포지토리만 유료입니다. 이번 회에선 Docker Hub를 사용해 이미지를 업로드해보도록 하겠습니다.

우선 https://hub.docker.com/ 에 접속해서 회원가입을 해주세요.

회원가입을 마치 신후 로컬 시스템에서 Docker Hub에 로그인을 해야 합니다. 터미널에서 아래 명령어를 입력해주세요.

docker login
ShellScript

커맨드 실행 후 나오는 user name 및 password 입력창에 올바른 user name 과 password를 입력하시면 됩니다. 여기서 user name은 로그인할 때 쓰이는 이메일이 아닌 계정 설정 때 지정하는 user name입니다.

로그인에 성공할 시 login success!라는 메시지가 보이실 거고 실패할 시 에러가 발생합니다. 반드시 로그인을 하셔야만 Docker Hub에 이미지를 업로드할 수 있으니 에러가 발생될 경우 해결하신 후 진행하시길 바랍니다.

이제 Docker Hub에 이미지를 업로드할 건데 기존에 빌드 한 이미지 이름을 살짝 변경을 해줘야 합니다. Docker Hub 업로드 시 이미지 이름을 지정하는 관례는 아래와 같습니다.

<계정이름>/<이미지이름>:<태그>
ShellScript

제 계정은 serendipity111011이므로 이미지를 serendipity111011/docker-to-kubernetes-nodejs로 빌드 하겠습니다.

docker build -t serendipity111011/docker-to-kubernetes .
ShellScript

위 커맨드로 새로 빌드를 하시거나 이미 존재하는 이미지의 태그를 변경하는 방법도 있습니다. 커맨드 구조는 아래와 같습니다.

docker tag <Image ID> <Username>/<Image Name>
ShellScript

그래서 저는 아래 커맨드를 실행하였습니다.

docker tag <IMAGE ID> serendipity111011/docker-to-kubernetes-nodejs
ShellScript

다시 한번 아래 커맨드를 실행해 이미지를 리스팅 해보면 저희가 지정한 태그로 이미지가 생성된 걸 볼 수 있습니다.

docker image ls
ShellScript

docker image ls
docker image ls

이제 생성된 이미지를 Docker Hub에 푸쉬 해보도록 하겠습니다. 커맨드 구조는 아래와 같습니다.

docker push <Image Name>
ShellScript

저는 아래 커맨드를 실행했습니다.

docker push serendipity111011/docker-to-kubernetes-nodejs
ShellScript

업로드가 완료되면 아래와 같은 결괏값이 보이게 됩니다.

docker push
docker push

이제 Docker Hub (https://cloud.docker.com/repository/list)에 접속하시면 푸시 하신 이미지가 업로드되어있는 걸 볼 수 있습니다.

docker hub
docker hub

업로드된 이미지를 클릭해보시면 아래와 같은 상세 화면이 실행됩니다.

docker hub
docker hub

태그 항목에 보면 저희가 빌드 할 때 태그를 설정 안 했기 때문에 latest로 설정이 돼있는 걸 볼 수 있습니다.

server.js 서버 파일을 아래와 같이 살짝 변경하고 새로운 버전을 빌드 후 Docker Hub에 푸시를 해보겠습니다.

const express = require('express');
const app = express();
const port = process.env.PORT;

app.get('/', (req, res) => {
    res.json({
        success: true,
        version:1
    });
});

app.listen(port, () => {
    console.log(`server is listening at localhost:${process.env.PORT}`);
});
JavaScript

태그를 변경하고 이미지를 빌드 한 다음에 다시 한번 Docker Hub에 푸시를 해보겠습니다. 저는 아래 커맨드를 사용하였습니다.

docker build -t serendipity111011/docker-to-kubernetes-nodejs:v1 .
docker push serendipity111011/docker-to-kubernetes-nodejs:v1
ShellScript

푸시가 완료되고 Docker Hub 이미지 상세페이지를 새로 고침하시면 아래와 같이 새로운 이미지 태그가(v1) 생성된 걸 보실 수 있습니다.

docker hub
docker hub

이렇게 이미지의 태그만 변경을 하고 푸시를 할 경우 같은 레포지토리에서 태그만 변형이 된 채로 저장이 됩니다. 여러 버전을 릴리스할 때 유용하고 나중에 Kubernetes에서 CI/CD 파이프라인을 구성할 때도 유용하게 사용됩니다. 이제 업로드된 이미지를 버전별로 로컬 시스템에서 실행해보도록 하겠습니다.

실행 방법은 기존 docker run 커맨드와 같습니다. 다만 이미지 이름 앞에 자신의 username을 추가해주시면 됩니다.

latest 태그의 이미지는 4000번 포트에, v1 태그의 이미지는 5000번 포트에 실행해보도록 하겠습니다 (계정 이름과 레포지토리 이름은 해당되시는 값으로 변경해주셔야 합니다). 여기서 새로 보여드릴 -d 플래그는 detached mode로 백그라운드 프로세스로 실행하라는 뜻입니다. 이럴 경우 실행 후 로그를 라이브로 보지 않고 다른 작업을 추가적으로 하실 수 있습니다.

docker run -d --env-file=.env -p 4000:3000 serendipity111011/docker-to-kubernetes-nodejs:latest
docker run -d --env-file=.env -p 5000:3000 serendipity111011/docker-to-kubernetes-nodejs:v1
ShellScript

실행이 완료되시면 http://localhost:4000에 접속하시면 {success:true}라는 값이 뜨고 http://localhost:5000에 접속하시면 {success:true, version:1}이라는 값이 보이시는 걸 알 수 있으십니다.

실행된 프로세스를 종료하기 위해 아래 커맨드를 실행해주세요

docker kill $(docker ps -q)
ShellScript

이로써 같은 레포지토리의 다른 태그 이미지를 외부 서버에서 다운로드하여 (사실 로컬에 캐싱이 이미 되어있었기 때문에 다운로드를 하지는 않았지만 안 되어있었을 경우 다운로드를 했을 겁니다.) 로컬에서 실행해보았습니다. 다음 시간부터는 docker-compose를 사용한 조금 더 복잡한 Container Orchestration을 해보도록 하겠습니다.

관련 포스트

플러터에서의 Immutable Programming: copyWith 함수 마스터하기!

플러터에서의 Immutable Programming: copyWith 함수 마스터하기!

서론 불변 프로그래밍: 현대 개발의 핵심 현대 소프트웨어 개발에서 불변 프로그래밍(Immutable Programming)의 중요성은 간과할 수 없는 요소입니다. 플러터(Flutter)에서도 마찬가지로 불변 프로그래밍 개념이 매우 중요하며, copyWith 함수는 이러한 불변성을 유지하는 데 핵심적인 역할을 합니다. 이 글에서는 플러터를 배우기 시작하는 개발자들에게 불변 프로그래밍의 중요성을 강조하고, copyWith 함수의 역할과 사용 방법에 대해 설명 해보겠습니다!...

ChatGPT가 이야기하는 2024년 개발자 로드맵

ChatGPT가 이야기하는 2024년 개발자 로드맵

서론 개발자의 여정을 시작하며 안녕하세요, 미래의 개발자 여러분! 오늘부터 시작하는 여러분의 개발 여정에 함께할 수 있어서 기쁩니다. 2023년은 기술이 매우 빠르게 변화하는 해였으며, 이러한 변화 속에서 개발자가 되기 위한 길은 더욱 다채롭고 흥미로워졌습니다. 이 로드맵은 초보자인 여러분이 개발의 세계에 첫발을 내딛는 데 필요한 기초부터 시작해, 점차 심화 단계로 나아가는 길을 안내해 드릴 것입니다. 백엔드 개발 이 글은 단순히 기술을 배우는 것 이상의 의미를 가집니다....

Flutter Freezed 플러그인! Entity Code Generation은 이거 하나로 끝!

Flutter Freezed 플러그인! Entity Code Generation은 이거 하나로 끝!

https://youtu.be/i5p6wXLAX7I 서론 Flutter 는 Code Generation 기능이 상당히 많이 활성화되어 있어요. 흔히들 많이 사용하는 json_serializable 라이브러리도 있고 retrofit 및 chopper 라이브러리도 있습니다. 오늘 알려드릴 freezed 또한 데이터 클래스에 편의 기능들을 제공해주는 code generation 라이브러리입니다. Freezed vs Json Serializable Code Generation 이라는...