매일공부

[NAS] SSH 접속 → 컨테이너 진입 → 안 쓰는 프로세스 정리, 명령어 모음 본문

IT/작업기록

[NAS] SSH 접속 → 컨테이너 진입 → 안 쓰는 프로세스 정리, 명령어 모음

julian 2026. 7. 30. 14:16

자주 쓰는데 매번 찾아보는 명령어들이라 한 번에 정리해둔다. 각 명령어마다 한 줄 요약을 먼저 적고, 그 아래에 옵션/단어별 설명을 붙였다.

1. SSH로 NAS 접속

~/.ssh/config에 Host 별칭을 등록해뒀다면 그대로 접속.

ssh <nas-host>

별칭이 없다면 계정/주소로 직접 접속.

ssh <계정>@<NAS주소>

한 줄 요약: ssh는 원격 서버에 안전하게 로그인하는 명령어. 계정@주소 형태로 "누가 어디에 접속할지"를 지정한다.

  • ssh: Secure Shell — 원격 서버에 암호화된 연결로 로그인하는 프로그램
  • <계정>@<NAS주소>: @ 앞은 로그인할 사용자 계정, 뒤는 접속할 서버 주소(IP 또는 도메인). ~/.ssh/config에 Host 별칭을 등록해두면 이 부분을 통째로 별칭 하나로 줄일 수 있다

2. 컨테이너 목록 확인

docker ps

실행 중인 컨테이너 이름/ID를 확인한다. 멈춘 컨테이너까지 보고 싶으면:

docker ps -a

한 줄 요약: docker ps는 지금 떠 있는 컨테이너 목록을 보여주는 명령어. -a를 붙이면 멈춘 것까지 다 보여준다.

  • docker: Docker CLI(명령줄 도구) 자체를 호출하는 명령어
  • ps: process status의 줄임말. 원래 리눅스에서 실행 중인 프로세스를 보여주는 명령어 이름에서 따온 것으로, docker ps는 "지금 실행 중인 컨테이너 목록"을 보여준다
  • -a: all — 실행 중인 것뿐 아니라 멈춰있는(stopped) 컨테이너까지 전부 보여주는 옵션

3. 컨테이너 안으로 진입

docker exec -it <컨테이너명> bash

한 줄 요약: 이미 떠 있는 컨테이너 안에 들어가서 명령어를 직접 칠 수 있게 해주는 명령어. -it을 빼먹으면 들어가도 아무것도 못 한다.

  • exec: execute — 이미 실행 중인 컨테이너 안에서 새로운 명령을 실행한다는 뜻. (컨테이너를 새로 만드는 run과 다르다 — exec은 "이미 떠 있는 컨테이너"가 대상)
  • -i: interactive — 표준입력(stdin)을 열어둔다. 이게 없으면 컨테이너 안에 들어가도 내가 입력하는 게 전달되지 않는다
  • -t: tty(가상 터미널) — 터미널 화면을 붙여준다. 이게 없으면 셸이 실행은 되지만 사람이 보기 편한 대화형 화면이 안 나온다
  • -it: -i와 -t를 합쳐서 쓴 것. 둘 다 있어야 "사람이 손으로 명령을 치면서 들어가 있는" 대화형 세션이 된다
  • <컨테이너명>: 대상 컨테이너의 이름 또는 ID (docker ps로 확인한 값)
  • bash: 컨테이너 안에서 실행할 명령. 여기서는 배시 셸을 실행해서 그 안에서 계속 다른 명령을 칠 수 있게 하는 것

-it을 빼고 docker exec <컨테이너명> bash만 실행하면, bash가 실행되긴 하지만 명령을 입력할 방법도 없고 화면도 제대로 안 나와서 사실상 아무것도 못 하고 바로 끝나버리는 것처럼 보인다. 사람이 직접 손으로 명령어를 치면서 들어가 있으려면 -it이 항상 필요하다. (반대로 스크립트 안에서 한 번 명령만 실행하고 빠질 때는 -it 없이 써도 된다 — 예: docker exec <컨테이너명> ls /app.)

들어가면 그 컨테이너 안에서 python manage.py runserver, migrate 같은 명령어를 직접 실행할 수 있다.

4. 터미널을 닫아버려서 컨테이너 안 프로세스가 안 죽을 때

SSH로 컨테이너 접속해서 runserver를 띄워놓고 터미널을 그냥 닫아버리면, 그 프로세스가 고아 상태로 컨테이너 안에 계속 살아있는 경우가 많다. (SIGHUP이 컨테이너 안까지 안 전달되는 경우가 많아서 그렇다.) 이럴 때 컨테이너를 재시작할 필요는 없고, 그 프로세스만 찾아서 죽이면 된다.

방법 1 — 호스트에서 바로 프로세스 확인

docker top <컨테이너명>

한 줄 요약: 컨테이너 안에 들어가지 않고도, 호스트에서 그 컨테이너 안의 프로세스 목록을 바로 볼 수 있는 명령어.

  • top: 원래 리눅스에서 현재 실행 중인 프로세스를 실시간으로 보여주는 명령어 이름. docker top은 그 컨테이너 버전으로, docker exec 없이도 호스트에서 컨테이너 내부 프로세스 목록(PID 포함)을 조회한다

방법 2 — 컨테이너 안에 다시 들어가서 죽이기

docker exec -it <컨테이너명> bash
ps aux | grep runserver | grep -v grep
kill <PID>        # 안 죽으면 kill -9 <PID>

한 줄 요약: 컨테이너 안에서 실행 중인 프로세스를 이름으로 찾아서(ps aux | grep), 그 번호(PID)로 종료(kill)한다.

  • ps aux: 현재 실행 중인 모든 프로세스를 자세히 보여주는 명령어
    • a: 다른 사용자가 실행한 프로세스까지 포함
    • u: 사용자 이름, CPU/메모리 사용량 등 자세한 정보(user-oriented format) 포함
    • x: 터미널에 연결 안 된 프로세스(백그라운드 프로세스 등)까지 포함
  • | (파이프): 왼쪽 명령의 출력 결과를 오른쪽 명령의 입력으로 그대로 넘겨주는 기호
  • grep runserver: 입력받은 텍스트 중에서 runserver라는 문자열이 포함된 줄만 걸러서 보여주는 명령어. 즉 ps aux | grep runserver는 "전체 프로세스 목록 중에서 runserver가 들어간 줄만 보여줘"라는 뜻
  • kill <PID>: 지정한 PID(프로세스 번호)의 프로세스를 종료 요청하는 명령어. 기본은 정상 종료 신호(SIGTERM)를 보낸다
  • kill -9 <PID>: -9는 SIGKILL 신호 — 프로세스에게 정리할 시간을 주지 않고 강제로 즉시 종료시킨다. 일반 kill로 안 죽을 때 최후 수단으로 쓴다

방법 3 — 포트 기준으로 찾기 (PID를 못 찾을 때)

# 컨테이너 안에서
netstat -tlnp | grep 8000
# 또는
ss -tlnp | grep 8000

한 줄 요약: 프로세스 이름 대신, 그 프로세스가 점유하고 있는 포트 번호로 역추적해서 PID를 찾는 방법.

  • netstat: network statistics — 네트워크 연결 상태, 열려 있는 포트 등을 보여주는 전통적인 명령어
  • ss: socket statistics — netstat보다 최신이고 더 빠른 대체 명령어. 최근 리눅스 배포판에서는 netstat 대신 이걸 기본으로 쓰는 경우가 많다
  • -t: tcp — TCP 연결만 보여주는 옵션
  • -l: listening — 현재 접속을 기다리고 있는(listen 상태인) 소켓만 보여주는 옵션
  • -n: numeric — 호스트명/서비스명을 이름으로 변환하지 않고 숫자(IP, 포트번호) 그대로 보여주는 옵션 (변환 과정이 생략되어 더 빠름)
  • -p: process — 그 포트를 쓰고 있는 프로세스의 이름과 PID까지 같이 보여주는 옵션
  • grep 8000: 결과 중에서 포트 번호 8000이 들어간 줄만 걸러서 보여줌

나온 PID를 kill하면 된다.

그래도 안 되면

이렇게 해도 포트가 계속 점유되어 있으면 그때는 진짜 컨테이너 재시작이 필요할 수 있다. 다만 보통은 프로세스 kill로 해결된다 — 컨테이너 재시작은 최후의 수단으로 남겨두면 된다.

정리 순서 요약

SSH로 NAS 접속
  ↓
docker ps로 컨테이너 확인
  ↓
docker exec -it <컨테이너> bash 로 진입
  ↓
(터미널을 실수로 닫아서 프로세스가 안 죽었다면)
  ↓
docker top <컨테이너> 또는 컨테이너 안에서 ps aux / netstat로 PID 찾기
  ↓
kill <PID> (안 되면 kill -9)
  ↓
그래도 안 되면 컨테이너 재시작 (최후 수단)
Comments