Code server on Docker

1. 서론.

  • 에디터로 VSCode를 주로 사용합니다.
  • 고정된 장소에서는 데스크탑이나 랩탑 환경에서 VSCode로 개발 또는 문서 작성을 하지만, 이동 중 아이패드에서는 사용할 수 없어 불편합니다.
  • 아이패드용 VSCode 앱이 없기 때문이죠. 그렇다고 방법이 없는 것은 아닙니다. 웹 브라우저로 접속해 이용할 수 있도록 기능을 제공하니까요.
  • https://vscode.dev 에 접속해 사용 가능하지만 터미널 등의 기능에 제약이 있어서, 개인 서버에 설치해 사용하는 몇가지 방법을 알아봅니다.

 

2. Code CLI.

  • 문서: Command Line Interface (CLI)
  • VSCode를 설치하면 CLI도 함께 설치되며, CLI만 설치하는 것도 가능합니다. 터미널에서 code 명령어를 통해 파일 열기, 언어 변경, 플러그인 설치, 원격터널 생성, 서버 실행 등 VSCode의 여러 기능들을 실행할 수 있습니다.
  • Code server를 실행하기 위해 CLI가 설치되어 있어야 합니다. 설치/실행 방법은 간단합니다. https://code.visualstudio.com/download 에서 CLI를 다운받아 압축을 풀면 code 라는 파일이 있으며, 그것을 실행하면 됩니다.

2-1. Tunnel.

  • 문서: Developing with Remote Tunnels
  • 원격 터널은 원격의 VSCode를 제어할 수 있도록 해주는 기능으로, VSCode 또는 웹 브라우저를 통해 접속할 수 있습니다.
  • 아래는 알파인 리눅스 터미널에서 터널을 생성하는 과정입니다. 패키지 설치 명령어(doas apk add) 외에 다른 리눅스 배포판에서도 별반 다르지 않습니다.

      $ doas apk add curl git nodejs
      $ cd ~
      $ curl -Lk 'https://code.visualstudio.com/sha/download?build=stable&os=cli-alpine-x64' --output vscode_cli.tar.gz
      $ tar -xf vscode_cli.tar.gz
      $ ./code tunnel --accept-server-license-terms
          *
          * Visual Studio Code Server
          *
          * By using the software, you agree to
          * the Visual Studio Code Server License Terms (https://aka.ms/vscode-server-license) and
          * the Microsoft Privacy Statement (https://privacy.microsoft.com/en-US/privacystatement).
          *
          ✔ How would you like to log in to Visual Studio Code? · GitHub Account
          To grant access to the server, please log into https://github.com/login/device and use code 1A2B-3C4D
          ✔ What would you like to call this machine? · my-server
          [2024-05-04 10:24:11] info Creating tunnel with the name: my-server
    
          Open this link in your browser https://vscode.dev/tunnel/my-server/home/dockerer/services/code-server
    
  • code tunnel을 실행하면 어떤 계정을 사용할 것인지 묻습니다. 저는 GitHub을 선택했고 https://github.com/login/device 라는 링크에 접속해서 1A2B-3C4D와 같은 코드로 인증하라고 안내한 후 대기합니다.
  • 인증이 완료되면 원격 머신의 이름을 지정하라고 안내합니다. 저는 my-server 로 지정했습니다.
  • 이후 https://vscode.dev/tunnel/my-server/home/dockerer/services/code-server 와 같은 링크를 안내 해 주는데, 이후 해당 링크를 통해 웹 브라우저에서 VSCode를 사용할 수 있습니다.
  • 단점은, 보안으로 GitHub 접속이 막혀 있는 환경에서 이용할 수 없습니다.

2-2. Serve web.

  • Serve web이라는 명칭에서 알 수 있듯이 VSCode 웹 서버입니다.
  • Tunnel과는 다르게 GitHub 등의 인증 없이 바로 접속 가능합니다.
  • 아래는 알파인 리눅스 터미에서 웹 서버를 실행하는 과정입니다. 패키지 설치 명령어(doas apk add) 외에 다른 리눅스 배포판에서도 별반 다르지 않습니다.
      $ doas apk add curl git nodejs
      $ cd ~
      $ curl -Lk 'https://code.visualstudio.com/sha/download?build=stable&os=cli-alpine-x64' --output vscode_cli.tar.gz
      $ tar -xf vscode_cli.tar.gz
      $ ./code serve-web --host 0.0.0.0 --port 8080 --accept-server-license-terms --without-connection-token
          *
          * Visual Studio Code Server
          *
          * By using the software, you agree to
          * the Visual Studio Code Server License Terms (https://aka.ms/vscode-server-license) and
          * the Microsoft Privacy Statement (https://privacy.microsoft.com/en-US/privacystatement).
          *
          Web UI available at http://0.0.0.0:8080
    
  • 이제 웹 브라우저로 http://your-server-ip:8080 에 접속하면 VSCode를 사용할 수 있습니다.
  • code serve-web으로 실행 시 --without-connection-token 옵션을 주지 않으면, 접속 시 리다이렉트 되면서 URL의 tkn 파라미터가 유실되어 인증 실패 오류가 발생합니다. 이부분은 아직 해결방법을 찾지 못했습니다. 인증 실패 오류

 

3. Code server on Docker.

  • VSCode는 도커 이미지를 제공하지 않아 직접 빌드해 사용하는 방법으로 진행합니다.

3-1. 디렉토리 생성.

  • Docker non-root user를 docker-user로 지정했습니다.
  • scripts에는 쉘 스트립트들, data/vscode에는 세션별 데이터, data/vscode-server에는 VSCode 실행에 필요한 파일들과 확장 플러그인들, data/workspace에는 작업물이 저장되도록 구성했습니다.
      $ su - docker-user
      $ mkdir -p ~/workspace/code-server/scripts ~/workspace/code-server/data/vscode ~/workspace/code-server/data/vscode-server ~/workspace/code-server/data/workspace
      $ cd ~/workspace/code-server
    

3-2. Entrypoint shell scripts 작성.

  • 리눅스 도커 이미지는 root user로 실행됩니다. 하지만 보안상 실행파일은 root user로 실행하지 않습니다.
  • 도커 이미지 빌드 시 coder 라는 user가 생성되록 했고, 실행 시 환경변수를 통해 coder의 user id와 group id를 업데이트 하도록 스크립트를 작성했습니다.
  • 물론 uid, gid를 업데이트 하지 않아도 되지만, 볼륨 마운트 시 권한이 맞지 않을 수 있기에 맞추어 주는 스크립트를 entrypoint로 실행합니다.
  • 그리고, code serve-web 명령어를 coder 권한으로 실행하도록 했습니다.

      $ vi scripts/entrypoint.sh
          #!/bin/sh
    
          USER_NAME=coder
          IS_CHANGED=false
    
          ## Change group ID.
          if [ -n "${GID}" ] && [ "${GID}" != "`id -g ${USER_NAME}`" ]; then
              groupmod --gid ${GID} ${USER_NAME}
              IS_CHANGED=true
          fi
    
          ## Change user ID.
          if [ -n "${UID}" ] && [ "${UID}" != "`id -u ${USER_NAME}`" ]; then
              usermod --uid ${UID} --gid ${GID} ${USER_NAME}
              IS_CHANGED=true
          fi
    
          ## Change home directory owner.
          if ${IS_CHANGED}; then
              chown -R ${UID}:${GID} /home/${USER_NAME}
          fi
    
          ## Run code server.
          su -c '/usr/local/bin/code serve-web --host 0.0.0.0 --port ${PORT} --accept-server-license-terms --without-connection-token' ${USER_NAME}
    

3-3. Dockerfile 작성 및 빌드.

  • 개발 시에 사용할 리눅스 배포판을 기반으로 도커 이미지를 빌드합니다. 이미지 이름은 my-code-server로 태그했습니다.
  • 제가 Ubuntu를 선호해 Ubuntu 기반으로 Dockerfile을 작성했습니다.
  • coder를 sudoer로 등록하는 부분이 있는데, 시스템 관리도 가능하도록 하기 위해 super user로 등록했습니다. 이렇게 하면 VSCode 터미널에서도 super user 권한으로 명령어 실행이 가능합니다. 보안 상 시스템 접근이 불가해야 한다면 sudoer로 등록하지 않으면 됩니다.

      $ vi Dockerfile
          FROM ubuntu:24.04
    
          ENV DEBIAN_FRONTEND=noninteractive
    
          ## 패키지 설치.
          RUN apt-get update
          RUN apt-get install -y language-pack-ko sudo curl git nodejs
    
          ## 언어 설정.
          RUN locale-gen ko_KR.UTF-8
          ENV LANG ko_KR.UTF-8
          ENV LANGUAGE ko_KR:ko:en_US:en
          ENV LC_ALL ko_KR.UTF-8
    
          ## TimeZone 설정.
          ENV TZ=Asia/Seoul
          RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
    
          ## 사용자 생성 및 sudoer로 등록.
          RUN useradd -m coder
          RUN echo "coder ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/coder
    
          ## Code CLI 다운로드.
          RUN curl -Lk "https://code.visualstudio.com/sha/download?build=stable&os=cli-alpine-x64" --output ~/vscode_cli.tar.gz
          RUN tar -xf ~/vscode_cli.tar.gz -C ~/ && rm ~/vscode_cli.tar.gz
          RUN mv ~/code /usr/local/bin/code
          RUN code version use stable --install-dir /usr/local/bin/code
    
          ## Shell script 복사.
          RUN mkdir /code-server
          COPY ./scripts /code-server/scripts
          RUN chmod +x /code-server/scripts/*
    
          ## 디렉토리 전환.
          RUN mkdir -p /home/coder/workspace
          RUN chown -R $(id -u coder):$(id -g coder) /home/coder/workspace
          WORKDIR /home/coder
    
          ## Code server 실행.
          ENTRYPOINT /code-server/scripts/entrypoint.sh
      $ docker build --no-cache --file Dockerfile --tag my-code-server .
    

3-4. Docker compose로 실행.

  • 빌드한 도커 이미지인 my-coder-server를 컨테이너로 실행합니다.
  • 환경변수에 현재 로그인 한 사용자의 user id, group id가 사용되도록 UID=$(id -u) GID=$(id -g) 로 지정했고, 접속 포트는 8080으로 지정했습니다.
      $ vi compose.yaml
          version: "3"
          services:
              my-code-server:
                  image: my-code-server
                  container_name: my-code-server
                  restart: unless-stopped
                  environment:
                      - UID=${UID}
                      - GID=${GID}
                      - PORT=8080
                  volumes:
                      - ./data/vscode:/home/coder/.vscode
                      - ./data/vscode-server:/home/coder/.vscode-server
                      - ./data/workspace:/home/coder/workspace
                  ports:
                      - 8080:8080
      $ UID=$(id -u) GID=$(id -g) docker compose --file compose.yaml up --detach --force-recreate
    

3-5. 웹 브라우저로 접속해 사용.

  • http://your-server-ip:8080 으로 접속하면 VSCode 구동에 필요한 설치 파일들이 내려받아진 후 UI가 나타납니다.
  • 이제 아이패드에서도 사용 가능해졌습니다. VSCode web
0
Subscribe to my newsletter

Read articles from Albert Hongseok Gu directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Albert Hongseok Gu
Albert Hongseok Gu