
회사 프로젝트를 배포하기 전에 로컬 머신에서 먼저 컨테이너를 띄워 테스트해야 하는 상황이 있었습니다.
이때 기존 습관대로 -alpine 버전의 이미지를 선택해서 Dockerfile을 구성했고, 이후 컨테이너를 실행했습니다.
그런데 회사 보안 정책상 Docker Desktop 같은 GUI 도구를 사용할 수 없었고, 오직 터미널만으로 디버깅을 진행해야 했습니다.
(물론 이때까지는 GUI 없이는 도커 사용하는게 너무 어려웠는데, 퇴사하고는 오히려 GUI가 어색해진 상황이 되어서 이 때 보안 때문에 사용하지 못했던 게 저에게는 큰 공부가 되었던 것 같습니다ㅎ)
보통 컨테이너 내부로 들어갈 때는 습관적으로 아래 명령어를 사용했습니다.:
docker exec -it {컨테이너 이름} /bin/bash
그런데 이번엔 아래와 같은 오류가 발생했습니다.
exec: "/bin/bash": stat /bin/bash: no such file or directory
처음엔 당황했지만, alpine 이미지에는 기본적으로 /bin/bash가 포함되어 있지 않다는 사실을 겨우,, 생각해냈습니다….
alpine은 용량을 최소화한 경량 이미지이기 때문에 bash 대신 기본 쉘로 sh만 포함되어 있습니다.
따라서 아래와 같이 접근해야 합니다.
docker exec -it {컨테이너 이름} /bin/sh
이 명령어를 사용하니 정상적으로 컨테이너 내부에 접속할 수 있었습니다.
이번 일을 계기로 두 쉘의 차이점도 간단하게 정리해보았습니다.
| 항목 | /bin/sh | /bin/bash |
|---|---|---|
| 이름 | Bourne Shell | Bourne Again SHell |
| 위치 | /bin/sh | /bin/bash |
| 목적 | POSIX 표준을 따르는 기본 쉘 | 확장 기능을 포함한 고급 쉘 |
| 기능 수준 | 최소한의 쉘 기능만 제공 | 배열, 문자열 처리 등 고급 기능 지원 |
| 대화형 기능 | 제한적 | 히스토리, 자동완성, 프롬프트 제공 |
| 용량 | 매우 작음 | 비교적 큼 (alpine엔 기본 미포함) |
# 문자열 일부 추출 (bash만 가능)
name="chatgpt"
echo "${name:0:4}" # 결과: chat
# 배열 선언 (bash만 가능)
arr=(a b c)
echo ${arr[1]} # 결과: b
sh에서는 위와 같은 문법을 사용할 수 없어 오류가 발생합니다.
| 작업 | 명령어 |
|---|---|
| alpine 컨테이너 접속 | docker exec -it {컨테이너} /bin/sh |
| bash가 필요한 경우 (비추천) | 컨테이너 내부에서 apk add bash 실행 후 /bin/bash 사용 가능 |
참고로, bash를 굳이 써야 한다면 처음부터 debian이나 ubuntu 기반 이미지를 사용하는 것도 고려해볼 수 있습니다.
이번 경험을 통해 작은 이미지 하나라도, 어떤 환경에서 실행되는지에 따라 접근 방식이 달라질 수 있다는 점을 다시 한번 느꼈습니다.
alpine은 가볍고 빠르지만, bash가 없다는 점 때문에 디버깅이나 스크립트 실행 시 주의가 필요합니다.
특히 alpine을 사용해서 테스트하게 되면, (저는 특히 바로 배포가 아닌 로드밸런서랑 api gateway를 통해야했기 때문에) 디버깅이 너~~~무 어려웠습니다.
그래서 실제 배포 시에는 alpine을 사용했고, 그 전 단계까지는 무조건 /bin/bash를 사용할 수 있도록 하였습니다.