Firefish를 설치해보자 (비전문가 대상)

docker-compose로 firefish를 실행하자

docker-compose: 여러 docker를 한 번에 실행하자

docker-compose는 docker 여러개를 한꺼번에 실행하고 관리하기 위한 편의도구입니다.

firefish 가 실행되기 위해 필요한 프로그램은 두 가지로 나뉩니다.

  • firefish 가 직접적으로 실행하는 프로그램
    -> docker 이미지 안에 같이 들어갑니다.
  • firefish 가 직접 실행하지 않고, 실행중인 다른 프로그램과 상호작용해야 하는 경우
    -> 다른 docker 이미지로 만듭니다.

firefish가 직접적으로 실행하는 프로그램들은 별도로 관리를 해줄 필요가 없고, docker 이미지 안에 같이 들어있기만 하면 됩니다.

그렇지만, 실행중인 다른 프로그램과 상호작용해야 하는 경우, 프로그램 하나당 이미지는 하나만 만들어야 관리도 잘 되고 쓰기도 편하므로, firefish 와는 별도의 docker 이미지를 만들어서 사용하게 됩니다. (TMI: firefish가 필요로 하는 따로 실행되어야 하는 다른 프로그램은 firefish 이미지와는 완전히 분리되어 있으므로, 상황에 따라 firefish 외의 다른 프로그램은 docker 이미지를 안 쓰고 이미 설치된 프로그램을 쓸 수도 있어요.)

만들어준 환경 갖다쓰기

docker와 docker-compose를 쓰는 또다른 이유는 우리가 직접 만들 필요가 없다는 것 때문입니다.

보통 docker 이미지와 docker-compose의 설정파일은 개발자 측에서 미리 준비해주는 경우가 많고, firefish도 예외가 아닙니다. 이런저런 프로그램을 설치하느라 고생할 필요가 확 줄어드는거죠.

조금 밑에서 다시 다룰거지만, docker-compose의 설정 파일은 docker-compose.yml 이고, firefish의 코드 저장소에 이미 있습니다. 우리는 이걸 가져다 쓰기만 하면 되는거죠.

환경 구성 - 사용자 생성

편의를 위해, docker 명령어를 실행하기 위한 전용 사용자를 만듭시다. 이전과 크게 다르지 않습니다.

sudo useradd -m -s /bin/bash -g docker docker
  • docker라는 사용자를 만듭니다.
  • -m : /home/docker 폴더를 만듭니다. 이게 이 사용자의 홈 경로입니다.
  • -s : 실행할 셸을 /bin/bash 로 정합니다. (명령줄을 처리해줄 환경 결정 - 다른 종류도 있습니다)
  • -g docker: 새로 만드는 사용자의 그룹을 docker로 지정합니다. 이미 docker를 설치하면서 docker 그룹이 생겼기 때문에, 이 부분을 지정하지 않으면 docker 그룹이 이미 있는데 만드려고 해서 오류가 발생합니다.

실행 예시

ch@firefish-server:~$ sudo useradd -m -s /bin/bash -g docker docker
[sudo] password for ch:
ch@firefish-server:~$

해당 사용자로 전환해서 docker 명령어가 sudo 없이 되나 살펴봅시다.

sudo -iu docker
docker ps

실행 예시

ch@firefish-server:~$ sudo -iu docker
docker@firefish-server:~$ docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
docker@firefish-server:~$

앞으로 docker 관련 작업은 (1) 원래 사용자로 ssh 원격접속 후 (2) docker 사용자로 변경해서 진행하겠습니다.

docker-compose.yml 만들기

먼저 firefish를 위한 폴더를 만들고, 그 안에 firefish에서 제공하는 docker-compose.yml 을 붙여넣겠습니다.

docker-compose는 프로젝트 이름 단위로 관리되는데, 별도로 프로젝트 이름을 지정하지 않으면 현재 폴더의 이름이 사용됩니다. 그래서 새로운 폴더를 만들어야 합니다.

# firefish 라는 폴더를 만듭니다
mkdir firefish

# firefish 폴더로 이동합니다
cd firefish

nano 편집기를 열어 수동으로 붙여넣거나 (파일 링크: https://git.joinfirefish.org/firefish/firefish/-/blob/develop/docker-compose.yml)

nano docker-compose.yml
# Ctrl + V 혹은 우클릭으로 붙여넣은 뒤,
# Ctrl + O 로 저장,
# Ctrl + X 로 나갑니다.

wget이나 curl로 직접 파일을 다운받아서 저장할 수도 있습니다.
(파일의 내용만 다운받기 위해 링크가 좀 다릅니다.)

# "\" 기호를 줄 끝에 넣으면 줄바꿈을 해도 하나의 명령어로 인식합니다.
# wget 은 인터넷에서 웹페이지나 파일을 다운받는 명령어입니다.
# -O 명령어로 다운받은 파일을 docker-compose.yml 에 저장하고 있습니다.
wget -O docker-compose.yml \
     https://git.joinfirefish.org/firefish/firefish/-/raw/develop/docker-compose.yml

둘 중에 한 방법을 사용하시면 됩니다.

참고: head나 tail 명령어로 파일의 앞부분, 뒷부분만 출력해볼 수 있습니다.

실행 예시

docker@firefish-server:~$ mkdir firefish
docker@firefish-server:~$ cd firefish
docker@firefish-server:~/firefish$ pwd
/home/docker/firefish
docker@firefish-server:~/firefish$ wget -O docker-compose.yml https://git.joinfirefish.org/firefish/firefish/-/raw/devel
op/docker-compose.yml
--2023-08-15 05:51:51--  https://git.joinfirefish.org/firefish/firefish/-/raw/develop/docker-compose.yml
Resolving git.joinfirefish.org (git.joinfirefish.org)... 192.99.201.173, 2607:5300:60:5ead::ff:cafe
Connecting to git.joinfirefish.org (git.joinfirefish.org)|192.99.201.173|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 1617 (1.6K) [text/plain]
Saving to: ‘docker-compose.yml’

docker-compose.yml            100%[=================================================>]   1.58K  --.-KB/s    in 0s

2023-08-15 05:51:52 (741 MB/s) - ‘docker-compose.yml’ saved [1617/1617]

docker@firefish-server:~/firefish$ head docker-compose.yml
version: "3"

services:
  web:
    image: registry.joinfirefish.org/firefish/firefish
    container_name: firefish_web
    restart: unless-stopped
    depends_on:
      - db
      - redis
docker@firefish-server:~/firefish$

docker-compose.yml 파일 뜯어보고 이해하기

일단 뭐가 있는지 이해를 하고 실행해봐야겠죠. 이번에 복사해넣은 docker-compose.yml 파일에는 여러가지가 들어있습니다.

살펴보기 전에 전에 - yml 파일은 yaml 문법에 맞춘 파일

이 설정파일은 "yaml" 이라는 문법에 맞춰 작성된 텍스트 파일입니다. 들여쓰기 갯수 같은 부분이 맞아야지 정상적으로 인식됩니다. 어려운 문법이 아니니 굳이 찾아보실 필요까지는 없고, 주변의 문법을 보고 적당히 맞춰쓰시면 됩니다.

version 부분

제일 위에 version이 적혀있습니다. docker-compose가 이 설정파일을 읽을 때 어떤 버전으로 해석해야 할지를 지정합니다. 바꿀 일도 없고, 중요하지 않은 것 같네요.

version: "3"

service 부분 (핵심) - 어떤 컨테이너를 실행할지 지정

service 부분이 거의 대부분을 차지하고, 핵심 부분입니다. 앞 부분만 살짝 볼까요.

services:
  web:
    image: registry.joinfirefish.org/firefish/firefish
    container_name: firefish_web
# 생략

services: 밑에 여러가지가 있습니다. 한 번 이것부터 살펴볼까요.

  • web: firefish 본체입니다.
  • redis: "redis" 라는 프로그램입니다. 캐시 등의 역할을 합니다. (필수)
  • db: 데이터베이스입니다. 글을 작성하면 여기에 저장될 것입니다. (필수)

그 외에도 각 줄의 제일 앞에 "#" 를 붙여서 비활성화해놓은 부분들도 눈에 띄네요.

# (샾 기호) 를 그 줄에 나오는 첫 번째 글자로 적은 경우, 해당 줄은 없는 것처럼 무시됩니다. "주석처리" 라고 부르죠. 이런 걸로 도움말을 쓰기도 합니다. (언어에 따라 주석 문자는 다름)

  • meilisearch 혹은 sonic: 검색엔진입니다. 용량이나 성능을 얼마나 쓸 지 몰라 이번에는 사용하지 않을 겁니다.

지금 살펴본 것처럼, 각각의 꼭지는 개별 서비스를 의미합니다. 이 설정파일을 사용해서 docker-compose로 실행하면 각각의 서비스가 컨테이너로 실행될 것입니다. 여기에서는 web, redis, db 3개가 실행되겠네요.

web 서비스를 자세히 살펴보자

각각의 서비스는 docker 컨테이너를 실행하는 것입니다. 서비스 중 "web" 서비스 부분을 자세히 살펴보고, 어떤 이미지를 실행하는지 등을 확인해봅시다.

서비스 자세히 보기: 이미지와 컨테이너

  web:
    image: registry.joinfirefish.org/firefish/firefish
    container_name: firefish_web
  • image: 어떤 docker 이미지(저장된 환경)를 사용해서 컨테이너를 만들지 결정합니다. firefish 프로젝트에서 제공해주는 이미지를 활용할 것입니다.
    • 이미지 부분은 추후에 설명할거지만 현재는 바꿔야 합니다.
  • container_name: 생성된 컨테이너(만들어지는 환경)의 이름을 정합니다. 이 부분을 정하지 않으면... 제 기억이 맞으면 서비스의 이름을 사용했을 거에요. 아님말구요~
  • 여기에는 없지만, 가끔 build가 있는 경우도 있습니다. Dockerfile에서 이미지를 만들어서 사용할 때 build를 사용합니다. 내가 개발자라는 전제 하에, firefish를 직접 수정할 일이 있을 때 쓰면 좋겠죠?

서비스 자세히 보기: 재시작, 의존성

  web:
    # ...생략...
    restart: unless-stopped
    depends_on:
      - db
      - redis
  • restart: 수동으로 정지하지 않은 경우, 서비스가 멈췄을 때 재시작하도록 설정했습니다.
    • 컨테이너는 컨테이너에서 실행한 프로그램이 정상이던 비정상이던 종료되면 컨테이너가 종료된 것으로 취급합니다. 애초에 프로그램 하나를 실행하기 위해 만든 격리환경이니까요.
    • 이 경우에는 firefish 프로그램이 종료되면 재시작하겠죠?
  • depends_on: 이 서비스는 db, redis 서비스가 실행된 이후에 실행될 것입니다. docker-compose를 사용하면 이렇게 여러개의 격리된 프로그램을 한 번에 실행할 때 유용합니다.

서비스 자세히 보기: 포트, 네트워크

  web:
    # ...생략...
    ports:
      - "3000:3000"
    networks:
      - calcnet
#     - web
  • port: 격리되지 않은 컴퓨터의 통신 포트 3000번(왼쪽)을 docker로 격리된 포트 3000번(오른쪽)에 연결해줍니다.

이 그림 기억하시나요?

그 때는 포트번호가 무엇인지 몰라서 12345를 넣었었죠. 이걸 고치자면

중요한 부분만 확대를 해볼게요

이렇게 됩니다.

  • networks: "calcnet" 이라는 가상의 네트워크에 이 서비스(컨테이너)를 연결합니다.
    • docker-compose로 실행되는 서비스끼리만 통신을 허용하고 싶을 때 사용되는 방법이에요.
    • docker 격리환경 외부랑 소통하는 방법은 위의 port 설정으로 3000번과 연결해주었으니 괜찮습니다.
    • calcnet인 이유는 firefish의 예전 이름이 calckey여서 그렇습니다. 임의로 지정한 거죠. 설정파일의 아래쪽에 보면 network 부분이 있을거에요.

서비스 자세히 보기: 환경변수

  web:
    # ...생략...
    environment:
      NODE_ENV: production
  • environment: 프로그램이 실행될 때 확인할 수 있는 값인 환경변수(environment variable)를 전달해줍니다. 여기에서는 NODE_ENV 라는 환경변수로 production을 넣어주네요. firefish가 개발환경이 아닌 서비스(프로덕션) 환경에서 돌아가도록 지시하는 역할을 합니다.

하나 더 봐야합니다. 데이터베이스 (db) 는 환경변수를 다른 방식으로 전달받고 있거든요.

  db:
    # ...생략...
    env_file:
      - .config/docker.env

환경변수는 docker-compose.yml 에 직접 적을수도 있지만, env_file 설정을 사용하면 특정한 파일에 "환경변수이름=값" 형태로 여러개를 적어서 전달할 수도 있습니다.

  • env_file: 환경변수를 직접 docker-compose.yml 에 적는 대신, 아래에 적혀있는 파일에서 불러와서 서비스에 전달합니다.
    • .config/docker.env 파일에서 읽어오겠네요. ".config" 는 폴더였군요!

서비스 자세히 보기: 볼륨 (저장공간)

대망의 볼륨 부분입니다.

볼륨에는 여러가지 모드가 있지만, 여기에서는 컴퓨터의 특정 파일/폴더를 컨테이너 환경에 연결시켜주는 역할을 합니다.

여기를 설정하지 않으면, 컨테이너가 삭제되면 컨테이너와 함께 파일들이 날아가버리게 됩니다. 그만큼 중요하죠.

    volumes:
      - ./files:/firefish/files
      - ./.config:/firefish/.config:ro

왼쪽이 컴퓨터의 파일/폴더, 오른쪽이 컨테이너로 격리된 환경에 나타날 경로입니다.

  • ./files:/firefish/files   ->   업로드한 파일이 여기에 저장됩니다
    • 빌린 컴퓨터의 환경: ./files 폴더
      ("."은 현재 경로니까 여기서는 /home/docker/firefish/files 폴더가 됩니다)
    • 컨테이너로 격리된 환경에는: /firefish/files 폴더에 나타납니다.
  • ./.config:/firefish/.config:ro   ->   firefish의 설정(파일 혹은 폴더)를 격리환경 내에 노출시켜줍니다.
    • 빌린 컴퓨터의 환경: ./.config 파일
      • 파일 혹은 폴더의 이름은 점(.)으로 시작하는 ".config" 입니다. (점으로 시작하니까)
      • "." 경로는 현재경로니까
        전체 경로는 /home/docker/firefish/.config 가 되겠네요.
    • 컨테이너로 격리된 환경에서는: /firefish/.config 파일 (혹은 폴더) 로 나타납니다.
    • ro: 컨테이너 내부에서는 수정할 수 없게 읽기전용(read only)으로 못박아놨습니다.

나머지 부분은 비슷하니까 설명하지 않아도 될 거 같아요.

설정파일 마련하기

잠깐... 설정파일이라구요? 네, 설정파일이 있습니다. 가이드를 보고 설정파일을 먼저 준비하고 나아갑시다.

Firefish의 문서(*도움말)에는 docker와 docker-compose로 firefish를 실행하고 싶은 경우를 위한 도움말이 준비되어 있습니다.

설정파일 다운받기

글에 따르면 설정파일을 2개 마련해야 합니다.

cp .config/example.yml .config/default.yml
cp .config/example.env .config/docker.env

두 개를 복사하라고 되어있는데, 이 파일들은 firefish의 소스코드 폴더(저장소repository라고 부릅니다)에 같이 들어있습니다.

소스코드를 빌린 컴퓨터에 받아놓지는 않았죠? 그래서 홈페이지에서 다운받아서 넣어줄 겁니다.

docker-compose.yml 다운받았던 거 기억나시죠? 비슷한 방법으로 할 겁니다. 방법은 두 가지에요.

  • nano로 파일을 만들고 붙여넣고 저장
  • wget이나 curl로 현재경로에 바로 다운받기

먼저 .config 폴더를 만들기부터 합시다. 그리고 .config 폴더로 들어가자구요.

mkdir .config
cd .config

실행 예시

docker@firefish-server:~/firefish$ mkdir .config
docker@firefish-server:~/firefish$ cd .config
docker@firefish-server:~/firefish/.config$ pwd
/home/docker/firefish/.config
docker@firefish-server:~/firefish/.config$

이제 파일을 다운받아서. 아래의 두 개의 파일입니다

  • .config/example.yml : 최신 버전 / 글을 쓰는 당시의 버전
    • .config/default.yml 에 저장합니다.
      nano default.yml 로 편집기를 연 뒤, 붙여넣고 - 저장하고 - 닫습니다.
    • 다운로드 명령어:
      # 다운받은 파일을 default.yml에 저장합니다.
      wget -O default.yml https://git.joinfirefish.org/firefish/firefish/-/raw/develop/.config/example.yml
  • .config/docker_example.env : 최신 버전 / 글을 쓰는 당시의 버전
    • .config/docker.env 에 저장합니다.
      nano docker.env 로 편집기를 연 뒤, 붙여넣고 - 저장하고 - 닫습니다.
    • 다운로드 명령어:
      # 다운로드 받은 파일을 docker.env 에 저장합니다.
      wget -O docker.env https://git.joinfirefish.org/firefish/firefish/-/raw/develop/.config/docker_example.env

이걸로 설정파일을 마련했습니다.

설정 바꾸기

설정파일의 틀을 마련했으니 이제 세세한 부분을 필요에 맞게 수정하면 됩니다.

default.yml 바꾸기 (firefish의 설정)

firefish가 읽어보는 설정파일은 default.yml 입니다. nano로 default.yml을 열어서 몇몇 부분을 바꾼 뒤 저장해줍시다.

nano default.yml
# 방향키로 이동하고, Ctrl + O (후 엔터) 로 저장하고, Ctrl + W 로 나가시면 됩니다.

수정할 부분은 그리 많지 않습니다.

url: 홈페이지의 주소

#   ┌─────┐
#───┘ URL └─────────────────────────────────────────────────────

# Final accessible URL seen by a user.
url: https://example.com/

firefish를 운영할 최종 주소를 적습니다. 저는 lake.naru.cafe 니까...

#   ┌─────┐
#───┘ URL └─────────────────────────────────────────────────────

# Final accessible URL seen by a user.
url: https://lake.naru.cafe/

로 바꾸었습니다.

포트 부분은 수정하지 않음

포트 부분에 아까 보여드렸던 그림이랑 같은 내용이 나와있습니다.

#                 +----- https://example.com/ ------------+
#   +------+      |+-------------+      +----------------+|
#   | User | ---> || Proxy (443) | ---> | Firefish (3000) ||
#   +------+      |+-------------+      +----------------+|
#                 +---------------------------------------+

다시 볼까요?

같은 거에요. 3000번 포트를 그대로 사용할 것이니 바꾸지 않습니다.

데이터베이스 계정과 암호를 바꾸자

firefish에 작성한 글은 모두 데이터베이스 안에 들어가게 됩니다.

  • 데이터베이스 프로그램 이름: PostgreSQL (포스트그레_에스큐엘(혹은 시큐얼))
  • docker-compose.yml 의 서비스 이름: db

firefish는 이 설정을 통해 데이터베이스와 통신하게 됩니다. 이 설정들은 PostgreSQL 이라는 데이터베이스 프로그램의 내부에서 관리하는 것입니다.

설정할 것은 4가지인데, 3가지만 바꾸겠습니다.

  • 데이터베이스 주소:
    • firefish가 데이터베이스에 접속하는데 필요합니다.
    • docker-compose.yml 내부망 환경에서는 서비스의 이름이 주소가 됩니다.
    • firefish측 설정 이름 (default.yml): host
    • 서비스 이름이 db었으므로, db로 바꿔줍니다.
  • 데이터베이스 이름 (변경하지 않음)
    • firefish측 설정 이름 (default.yml): db
    • postgres측 설정 이름 (docker.env): POSTGRES_DB
    • 템플릿에 있는 값인 "firefish"를 그대로 쓸 겁니다.
  • 데이터베이스 사용자 이름
    • firefish측 설정 이름 (default.yml): user
    • postgres측 설정 이름 (docker.env): POSTGRES_USER
  • 데이터베이스 사용자 암호
    • firefish측 설정 이름 (default.yml): pass
    • postgres측 설정 이름 (docker.env): POSTGRES_PASSWORD
#   ┌──────────────────────────┐
#───┘ PostgreSQL configuration └────────────────────────────────

db:
  host: localhost
  port: 5432
  #ssl: false
  # Database name
  db: firefish

  # Auth
  user: example-firefish-user
  pass: example-firefish-pass

저는 사용자 ID와 암호를 다음과 같이 바꾸겠습니다. (실제로는 다른 값을 쓸 거지만, 예시로 보여드릴게요)

  • user: lakeDatabaseUser
  • pass: lakeDatabaseUserTheAssasinOfYourTime
#   ┌──────────────────────────┐
#───┘ PostgreSQL configuration └────────────────────────────────

db:
  host: db
  port: 5432        # 수정하지 않습니다 (보통 기본값이 5432임)
  #ssl: false       # 수정하지 않습니다
  # Database name
  db: firefish      # 이 값을 그대로 씁니다

  # Auth
  user: lakeDatabaseUser
  pass: lakeDatabaseUserTheAssasinOfYourTime

암호에 특수문자를 넣었는데 뭔가 안 된다면, 쌍따옴표로 감싸봅시다. "lakeDatabaseUserTheAssasinOfYourTime" 이렇게요. yaml 문법에서는 이렇게 감싸면 이 영역이 문자열(텍스트)이다 라는 표시입니다.

안전을 위해 데이터베이스의 ID와 암호는 바꿔두자

docker-compose.yml 의 설정에 따르면, 데이터베이스는 외부에서 직접 접속할 수 없습니다. 그런데 왜 ID와 암호를 바꿔야 할까요? 혹시 모를 상황을 대비하기 위함입니다.

firefish에 취약점이 있다던가 해서 접속할 수 있는 길이 나도 모르는 사이에 생길수도 있거든요. 그런 일이 발생하면, 관리자 권한을 탈취당할 수 있는 위험이 있기에 암호는 꼭 바꿔줘야 합니다. (해커가 글을 싸악 날려버리거나... 무서운 일이죠;)

Redis 설정: host만 변경

Redis는 자주 사용되는 정보를 저장해놓았다가 빠르게 돌려준다던가 하는 등에 사용되는, 정보 관리용 프로그램입니다. 위의 PostgreSQL 데이터베이스와 비슷하지만, 갖고 있는 정보를 파일에 저장하지 않고 프로그램 자기 자신만 알고있어서 굉장히 빠르게 동작하죠. 대신 프로그램이 꺼지면 가지고 있던 정보가 다 날아갑니다. 그래서 보통 날아가도 상관 없는 자료들을 저장합니다. (이것 외의 역할도 있어요.)

Redis에는 파일에 저장하는 위의 데이터베이스(PostgreSQL)보다 덜 중요한 데이터가 저장되어 있습니다. 탈취당한다고 해서 전권을 빼앗기거나 하지는 않아요. 그래서 로그인을 인증하지 않는 기본 모드를 그대로 사용합니다. 어차피 이 상황에서는 외부에서 직접 접근할 수 없으니까요.

다른 컴퓨터에서 Redis를 실행한다면 user, password, host, port 등을 바꿔야겠죠? 그것 외에도 인증 모드를 사용하도록 설정도 해줘야 합니다.

이번에는 접속이 가능하게 host 부분만 바꿔줍시다.

#   ┌─────────────────────┐
#───┘ Redis configuration └─────────────────────────────────────

redis:
  host: localhost
  port: 6379

redis의 주소는 서비스의 이름입니다. localhost를 redis로 바꿔줍시다.

#   ┌─────────────────────┐
#───┘ Redis configuration └─────────────────────────────────────

redis:
  host: redis
  port: 6379

docker.env 파일도 바꾸자

현재로서는 docker.env 파일의 설정은 데이터베이스 설정 뿐이었습니다. 위에서 설정한 것과 맞춰주면 됩니다.

# db settings
POSTGRES_PASSWORD=example-firefish-pass
POSTGRES_USER=example-firefish-user
POSTGRES_DB=firefish

저는 이렇게 바꿨어요. (예시)

# db settings
POSTGRES_PASSWORD=lakeDatabaseUser
POSTGRES_USER=lakeDatabaseUserTheAssasinOfYourTime
POSTGRES_DB=firefish

쌍따옴표는 넣으면 안 되는 걸로 알고있습니다. (정확하지 않음)

docker-compose.yml 의 firefish 에 버전 지정하기

진행하기 전에 한 가지 해둬야 할 일이 있습니다.

docker-compose.yml 의 "web" 서비스는 firefish를 실행하는데, 거기에는 버전이 적혀있지 않습니다. 이러면 내가 모르는 사이에 최신버전이 다운받아져요! 최신버전이 문제가 있으면 난리가 나게 됩니다....

또한, 저희가 빌린 컴퓨터는 핸드폰이 사용하는 것과 같은 "ARM64" 라는 아키텍처로 되어있습니다 (참고: "컴퓨터를 빌리자" 편). 버전을 지정하지 않으면, 일반적인 컴퓨터의 아키텍처인 "x64 (AMD64)" 버전이 다운받아지게 됩니다. 이건... 지금 저희가 마련한 환경에서는 실행되지 않아요. 마스토돈 같은 다른 프로젝트의 경우 같은 이름으로 여러 아키텍처를 제공해주는 "multiarch" 버전을 제공해주지만 firefish는 아직 그렇지 않네요... 이 부분은 나중에 바뀌겠죠?

2024-03-02 추가

네, 바뀌었습니다. Firefish 메인 개발자가 현생이 바쁘다고 공지를 남긴 이후로 개발은 불완전하게나마 다른 사용자들에게 넘어갔고, 공식 이미지가 "multiarch" 로 올라오고 있습니다.

직접 확인하기: (현재 최신인 v20240301)

docker manifest inspect registry.firefish.dev/firefish/firefish:v20240301

아래 실행결과에 보시면 "architecture" 에 "amd64" 와 "arm64"가 다 있죠? 이제는 아키텍처와 무관하게 버전만 제대로 명시해주면 됩니다.

ch@ch-zenbook14:/mnt/c/Users/sftbl$ docker manifest inspect registry.firefish.dev/firefish/firefish:v20240301
{
   "schemaVersion": 2,
   "mediaType": "application/vnd.docker.distribution.manifest.list.v2+json",
   "manifests": [
      {
         "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
         "size": 1246,
         "digest": "sha256:df09b6849a33a17bb796af183fd4e250986ae224f94f5e9cf2531b72ea4db38c",
         "platform": {
            "architecture": "amd64",
            "os": "linux"
         }
      },
      {
         "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
         "size": 1246,
         "digest": "sha256:f9382a05252789cd717dff40d4997cea5da429de3870f9783b20ccc54bc8529c",
         "platform": {
            "architecture": "arm64",
            "os": "linux",
            "variant": "v8"
         }
      }
   ]
}

이제 아래 내용에서 "arm64" 태그 부분만 버전인 "v20240301" 같은 걸로 바꿔주시면 됩니다.

기존 내용

그래서 버전을 명시해줘야 합니다.

버전 정보는 어디에 있을까요? https://git.joinfirefish.org/firefish/firefish/container_registry/1 이 페이지에 있습니다. 좀 살펴봅시다.

  • amd64: "태그" 입니다. 버전에 읽고 쓰기 편한 이름을 달아놓은 것입니다.
    • 보통은 이 부분을 쓰지만, "arm64"라고만 적혀있고 버전 이름이 적혀있지 않습니다. 버전 업데이트를 어떻게 알라고... 이걸 신뢰하고 쓰기에는 꺼려지는군요.
  • digest: SHA256 이라는 암호화 알고리즘을 사용해서, 고유한 이름을 만들어낸 것입니다. 이게 진짜 이름으로, 이번에는 이것의 짧은 버전 (앞에서부터 7자리 글자) 를 사용해서 명시할 겁니다.

사용할 때에는 이런 방식으로 사용합니다.

registry.joinfirefish.org/firefish/firefish:arm64

끝에 "arm64" 가 붙어있는 게 보이시죠?

위에서 설명한 모종의 이유로 digest 부분을 대신 사용할 것입니다. 형식이 조금 다르고 아쉽게도 풀버전을 가져와야 합니다...

registry.joinfirefish.org/firefish/firefish@sha256:ff2b609bb0ddd617127b2514c0f7cc61b352f3496e16689d279fb4a749580385

지금은 "@sha256:ff2b609...생략" 이지만, 추후 버전이 업데이트되면 그걸로 바꾸면 됩니다.

실제 docker-compose.yml 파일에 적용해볼까요. 일단 "cd .." 을 입력해서 /home/docker/firefish 로 돌아가야겠죠? 그 다음에 파일을 nano로 열어 수정합시다.

실행 예시

  GNU nano 6.2                                       docker-compose.yml                                                 version: "3"

services:
  web:
    image: registry.joinfirefish.org/firefish/firefish@sha256:ff2b609bb0ddd617127b2514c0f7cc61b352f3496e16689d279fb4a749580385
    container_name: firefish_web
    restart: unless-stopped
    depends_on:
      - db
      - redis

docker-compose 로 firefish 실행하기

이제 진짜로 docker-compose 로 firefish를 포함한 프로그램들을 실행할 준비가 되었습니다.

원래는 명령어 하나로 끝날 일이긴 한데, 보통 초기 설정이 필요해서 초기 설정에 관한 가이드가 같이 제공되는 경우가 많습니다. 그런데 가이드를 자세히 읽어보니 그건 개발용이네요?

그러면 이제 명령어 하나만 실행하면 됩니다.

docker compose up -d
  • docker의 최신 버전을 설치한 경우, docker-compose 라는 명령어가 docker compose 로 대체되었습니다. 우리는 최신버전을 깔았으니까요...
  • "up" 을 실행하면, docker-compose.yml 파일에 있는 모든 서비스가 실행됩니다.
  • -d 혹은 --daemon 옵션을 추가하면, 결과를 화면에 출력하지 않고 자기가 알아서 혼자 돌아가게 됩니다. 이걸 떼고 실행하면 (sudo docker compose up), Ctrl + C 로 명령을 강제로 종료하면 서비스도 같이 꺼집니다.

첫 실행 (-d 떼고 로그도 보기)

첫 실행만 -d를 떼고 실행해서 잘 돌아가나 봅시다.

docker compose up

실행 예시

docker@firefish-server:~/firefish$ docker compose up
[+] Running 3/0
 ✔ Container firefish_db     Created                                                                                                                                    0.0s
 ✔ Container firefish_redis  Created                                                                                                                                    0.0s
 ✔ Container firefish_web    Created                                                                                                                                    0.0s
Attaching to firefish_db, firefish_redis, firefish_web
firefish_redis  | 1:C 19 Aug 2023 16:51:14.469 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
firefish_redis  | 1:C 19 Aug 2023 16:51:14.469 # Redis version=7.0.12, bits=64, commit=00000000, modified=0, pid=1, just started
firefish_redis  | 1:C 19 Aug 2023 16:51:14.469 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
...생략...
firefish_web    | query: SELECT * FROM current_schema()
firefish_web    | query: SELECT version();
firefish_web    | query: SELECT * FROM "information_schema"."tables" WHERE "table_schema" = 'public' AND "table_name" = 'migrations'
firefish_web    | query: CREATE TABLE "migrations" ("id" SERIAL NOT NULL, "timestamp" bigint NOT NULL, "name" character varying NOT NULL, CONSTRAINT "PK_8c82d7f526340ab734260ea46be" PRIMARY KEY ("id"))
firefish_web    | query: SELECT * FROM "migrations" "migrations" ORDER BY "id" DESC
firefish_web    | 0 migrations are already loaded in the database.
firefish_web    | 191 migrations were found in the source code.
firefish_web    | 191 migrations are new migrations must be executed.
firefish_web    | query: START TRANSACTION
firefish_web    | query: CREATE TYPE "log_level_enum" AS ENUM('error', 'warning', 'info', 'success', 'debug')
firefish_web    | query: CREATE TABLE "log" ("id" character varying(32) NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "domain" character varying(64) array NOT NULL DEFAULT '{}'::varchar[], "level" "log_level_enum" NOT NULL, "worker" character varying(8) NOT NULL, "machine" character varying(128) NOT NULL, "message" character varying(1024) NOT NULL, "data" jsonb NOT NULL DEFAULT '{}', CONSTRAINT "PK_350604cbdf991d5930d9e618fbd" PRIMARY KEY ("id"))
firefish_web    | query: CREATE INDEX "IDX_8e4eb51a35d81b64dda28eed0a" ON "log" ("createdAt")
firefish_web    | query: CREATE INDEX "IDX_8cb40cfc8f3c28261e6f887b03" ON "log" ("domain")

와... 뭔가 기네요. 다운로드가 먼저 된 다음에 이런 화면들이 뜨게 됩니다.

처음에 실행되는 "CREATE INDEX" 같은 부분들이 firefish가 데이터베이스를 조작했다는 걸 나타내는 기록(로그)입니다.

좀 놔두면 로고가 나올겁니다.

실행 예시

firefish_web    |  ▄▄▄▄▄▄▄ ▄▄▄ ▄▄▄▄▄▄   ▄▄▄▄▄▄▄ ▄▄▄▄▄▄▄ ▄▄▄ ▄▄▄▄▄▄▄ ▄▄   ▄▄    ◯
firefish_web    | █       █   █   ▄  █ █       █       █   █       █  █ █  █      ○   ▄    ▄
firefish_web    | █    ▄▄▄█   █  █ █ █ █    ▄▄▄█    ▄▄▄█   █  ▄▄▄▄▄█  █▄█  █    ⚬     █▄▄  █▄▄
firefish_web    | █   █▄▄▄█   █   █▄▄█▄█   █▄▄▄█   █▄▄▄█   █ █▄▄▄▄▄█       █      ▄▄▄▄▄▄   ▄
firefish_web    | █    ▄▄▄█   █    ▄▄  █    ▄▄▄█    ▄▄▄█   █▄▄▄▄▄  █   ▄   █     █      █  █▄▄
firefish_web    | █   █   █   █   █  █ █   █▄▄▄█   █   █   █▄▄▄▄▄█ █  █ █  █     █ ● ●  █
firefish_web    | █▄▄▄█   █▄▄▄█▄▄▄█  █▄█▄▄▄▄▄▄▄█▄▄▄█   █▄▄▄█▄▄▄▄▄▄▄█▄▄█ █▄▄█     ▀▄▄▄▄▄▄▀
firefish_web    |  Firefish is an open-source decentralized microblogging platform.
firefish_web    |  If you like Firefish, please consider starring or contributing to the repo. https://git.joinfirefish.org/firefish/firefish

넵, 좋았어요. 잘 실행되네요. 이제 Ctrl + C 를 눌러 종료해버립시다.

실행 예시

^CGracefully stopping... (press Ctrl+C again to force)
Aborting on container exit...
[+] Stopping 3/3
 ✔ Container firefish_web    Stopped                                                                                                                                    0.4s
 ✔ Container firefish_db     Stopped                                                                                                                                    0.3s
 ✔ Container firefish_redis  Stopped                                                                                                                                    0.3s
canceled
docker@firefish-server:~/firefish$

up -d: 서비스로 실행하기

이제 -d를 넣고 실행해봅시다. 이렇게 하면 컴퓨터가 재부팅되어도 다시 켜질 거에요.

docker compose up -d

 실행 예시

docker@firefish-server:~/firefish$ docker compose up -d
[+] Running 3/3
 ✔ Container firefish_db     Started                                                                                                                                    0.5s
 ✔ Container firefish_redis  Started                                                                                                                                    0.5s
 ✔ Container firefish_web    Started                                                                                                                                    0.9s
docker@firefish-server:~/firefish$

오, 잘 되네요. 근데 잘 되는 건지는 어떻게 확인하죠?

logs: 로그 확인하기

컨테이너들이 남긴 기록(로그, log)들을 살펴보면 됩니다.

docker compose logs

아무 옵션 없이 실행하면 로그가 모두 출력됩니다. 장시간 실행한 경우 매우 곤란해질 수 있습니다...

도움말을 한 번 볼까요.

docker compose logs --help

실행 예시

docker@firefish-server:~/firefish$ docker compose logs --help

Usage:  docker compose logs [OPTIONS] [SERVICE...]

View output from containers

Options:
      --dry-run         Execute command in dry run mode
  -f, --follow          Follow log output.
      --no-color        Produce monochrome output.
      --no-log-prefix   Don't print prefix in logs.
      --since string    Show logs since timestamp (e.g. 2013-01-02T13:23:37Z) or relative (e.g. 42m for 42 minutes)
  -n, --tail string     Number of lines to show from the end of the logs for each container. (default "all")
  -t, --timestamps      Show timestamps.
      --until string    Show logs before a timestamp (e.g. 2013-01-02T13:23:37Z) or relative (e.g. 42m for 42 minutes)

 

docker compose logs -f --tail 100
  • -f 옵션을 붙이면, 로그 출력을 멈추지 않고 계속 따라서 지켜볼 수 있습니다.
    • Ctrl + C를 누르면 종료돼요.
  • --tail 100 을 붙이면, 마지막 100줄을 보게 돼요.

이렇게 하면 마지막 100줄부터 계속 지켜볼 수 있겠죠? 여기에 담기에는 너무 많아지니까, 저는 5줄만 볼게요.

실행 예시

docker@firefish-server:~/firefish$ docker compose logs -f --tail 5
firefish_web    | Please migrate your code to use AWS SDK for JavaScript (v3).
firefish_web    | For more information, check the migration guide at https://a.co/7PzMCcy
firefish_web    | (Use `node --trace-warnings ...` to show where the warning was created)
firefish_web    | INFO 1        [queue check-expired-mutings]   Checking expired mutings...
firefish_web    | DONE 1        [queue check-expired-mutings]   All expired mutings checked.
firefish_db     | 2023-08-19 16:56:45.822 UTC [1] LOG:  listening on IPv4 address "0.0.0.0", port 5432
firefish_db     | 2023-08-19 16:56:45.822 UTC [1] LOG:  listening on IPv6 address "::", port 5432
firefish_db     | 2023-08-19 16:56:45.826 UTC [1] LOG:  listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
firefish_db     | 2023-08-19 16:56:45.848 UTC [21] LOG:  database system was shut down at 2023-08-19 16:54:59 UTC
firefish_db     | 2023-08-19 16:56:46.004 UTC [1] LOG:  database system is ready to accept connections
firefish_redis  | 1:M 19 Aug 2023 17:03:31.138 * 10000 changes in 60 seconds. Saving...
firefish_redis  | 1:M 19 Aug 2023 17:03:31.138 * Background saving started by pid 17
firefish_redis  | 17:C 19 Aug 2023 17:03:31.145 * DB saved on disk
firefish_redis  | 17:C 19 Aug 2023 17:03:31.146 * Fork CoW for RDB: current 0 MB, peak 0 MB, average 0 MB
firefish_redis  | 1:M 19 Aug 2023 17:03:31.239 * Background saving terminated with success
^Ccanceled
docker@firefish-server:~/firefish$

잘 되네요.

down: 서비스 내리기

이제 꺼볼까요. "docker compose down" 을 실행하면 됩니다.

docker compose down

실행 예시

docker@firefish-server:~/firefish$ docker compose down
[+] Running 4/3
 ✔ Container firefish_web    Removed                                                                                                                                    0.4s
 ✔ Container firefish_db     Removed                                                                                                                                    0.2s
 ✔ Container firefish_redis  Removed                                                                                                                                    0.3s
 ✔ Network firefish_calcnet  Removed                                                                                                                                    0.0s
docker@firefish-server:~/firefish$

서비스가 모두 종료되고, 만들어졌던 컨테이너(격리환경)도 모두 삭제되었습니다. 다음에 다시 실행할 때 다시 만들거에요. 중요한 파일들은 모두 가상환경 바깥에 저장되어있으니까 괜찮겠죠?

firefish는 켰지만 아직은 접속 불가능

이번에는 docker-compose를 사용해서 성공적으로 firefish를 실행하는 데 성공했습니다. 하지만 아직 브라우저로 접근할 수는 없습니다. 외부에서 접근할 수 있는 안전한 통로를 만들어주지 않았기 때문이죠.

 

다음 장에서는 외부에서 접속할 수 있는 경로를 뚫어주기 위해, 위 그림의 "NGINX" 부분과 "HTTPS" 부분을 설정할 것입니다.

댓글

댓글 본문
버전 관리
sftblw
현재 버전
선택 버전
graphittie 자세히 보기