VSCode를 웹으로 접근해서 사용할 수 있도록 해주는 code-server를 소개한 적이 있다.

- Web based Visual Studio Code (Online VSCode)

 

공식적으로 제공해주는 docker image가 있긴 하지만,

이번에는 Kubernetes에 올려서 사용하기 위한 나만의 docker image를 만들어보려고 한다.

 

0. 작업 환경

  - 이하 과정을 진행한 환경은 다음과 같다.

    . OS: Ubuntu 18.04 Desktop

    . Docker: Docker version 20.10.7, build f0df350

 

  - Docker 설치는 다음 포스팅을 참고하기 바란다.

    . Docker Install (Ubuntu Server 20.04 - 64bit) - using Download

  - 지금 포스팅을 작성하는 시점에서의 최신 버전은 다음과 같다.

    . containerd.io_1.4.8-1_amd64.deb

    . docker-ce-cli_20.10.7~3-0~ubuntu-focal_amd64.deb

    . docker-ce_20.10.7~3-0~ubuntu-focal_amd64.deb

 

 

1. Dockerfile & Scripts

  - 아래 내용은 다음 링크를 참조했다.

    . https://git.nofla.me/k8s-projects/codekube

  - 위 내용 중 필요한 부분만 뽑아내고 재구성을 한 내용을 전체 공유하면 아래와 같다.

 

    . Dockerfile

 

FROM ubuntu:20.04

RUN apt-get update && apt-get upgrade -y
RUN DEBIAN_FRONTEND="noninteractive" apt-get install -y \
    wget \
    vim \
    curl \
    dumb-init \
    zsh \
    htop \
    locales \
    man \
    nano \
    git \
    procps \
    openssh-client \
    sudo \
    jq \
    openssl \
    bash-completion \
    dnsutils \
    lsb-release

RUN apt-get install -y python3 python3-pip python3-dev build-essential

RUN update-alternatives --install /usr/bin/python python /usr/bin/python3 1
RUN update-alternatives --install /usr/bin/pip pip /usr/bin/pip3 1

RUN apt-get install -y apt-utils locales
RUN locale-gen ko_KR.UTF-8
ENV LC_ALL ko_KR.UTF-8


RUN addgroup --gid 1000 code && \
    adduser --uid 1000 --ingroup code --home /home/code --shell /bin/bash --disabled-password --gecos "" code && \
    adduser code sudo
RUN chmod g+rw /home && \
    mkdir -p /home/code/workspace && \
    chown code:code /home/code/workspace -R


RUN echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers;


RUN USER=code && \
    GROUP=code
RUN curl -SsL https://github.com/boxboat/fixuid/releases/download/v0.5/fixuid-0.5-linux-amd64.tar.gz | tar -C /usr/local/bin -xzf - && \
    chown root:root /usr/local/bin/fixuid && \
    chmod 4755 /usr/local/bin/fixuid && \
    mkdir -p /etc/fixuid && \
    printf "user: $USER\ngroup: $GROUP\n" > /etc/fixuid/config.yml


RUN CODE_SERVER_VERSION=3.11.0 && \
    curl -sSOL https://github.com/cdr/code-server/releases/download/v${CODE_SERVER_VERSION}/code-server_${CODE_SERVER_VERSION}_amd64.deb && \
    sudo dpkg -i code-server_${CODE_SERVER_VERSION}_amd64.deb


RUN cat /usr/lib/code-server/lib/vscode/product.json \
    | jq '.extensionAllowedProposedApi[.extensionAllowedProposedApi | length] |= . + "ms-vsliveshare.vsliveshare" \
        | .extensionAllowedProposedApi[.extensionAllowedProposedApi | length] |= . + "ms-vscode.node-debug" \
        | .extensionAllowedProposedApi[.extensionAllowedProposedApi | length] |= . + "ms-vscode.node-debug2"' \
    > /usr/lib/code-server/lib/vscode/product.json_ \
    && mv /usr/lib/code-server/lib/vscode/product.json_ /usr/lib/code-server/lib/vscode/product.json


RUN mkdir /opt/default_home
ADD warehouse/.bashrc /opt/default_home


ENV PASSWORD=${PASSWORD:-password}
EXPOSE 8080

ADD warehouse/restart-codekube.sh /usr/local/bin/restart-codekube
ADD warehouse/code.sh /usr/local/bin/code
ADD warehouse/startup.sh /startup.sh


RUN chmod a+x /usr/local/bin/*

ENTRYPOINT ["/bin/bash", "/startup.sh"]

 

  - 필요한 스크립트 파일은 다음과 같다.

    . .bashrc

 

# ~/.bashrc: executed by bash(1) for non-login shells.
# see /usr/share/doc/bash/examples/startup-files (in the package bash-doc)
# for examples

# If not running interactively, don't do anything
case $- in
    *i*) ;;
      *) return;;
esac

# don't put duplicate lines or lines starting with space in the history.
# See bash(1) for more options
HISTCONTROL=ignoreboth

# append to the history file, don't overwrite it
shopt -s histappend

# for setting history length see HISTSIZE and HISTFILESIZE in bash(1)
HISTSIZE=1000
HISTFILESIZE=2000

# check the window size after each command and, if necessary,
# update the values of LINES and COLUMNS.
shopt -s checkwinsize

# If set, the pattern "**" used in a pathname expansion context will
# match all files and zero or more directories and subdirectories.
#shopt -s globstar

# make less more friendly for non-text input files, see lesspipe(1)
[ -x /usr/bin/lesspipe ] && eval "$(SHELL=/bin/sh lesspipe)"

# set variable identifying the chroot you work in (used in the prompt below)
if [ -z "${debian_chroot:-}" ] && [ -r /etc/debian_chroot ]; then
    debian_chroot=$(cat /etc/debian_chroot)
fi

# set a fancy prompt (non-color, unless we know we "want" color)
case "$TERM" in
    xterm-color|*-256color) color_prompt=yes;;
esac

# uncomment for a colored prompt, if the terminal has the capability; turned
# off by default to not distract the user: the focus in a terminal window
# should be on the output of commands, not on the prompt
#force_color_prompt=yes

if [ -n "$force_color_prompt" ]; then
    if [ -x /usr/bin/tput ] && tput setaf 1 >&/dev/null; then
    # We have color support; assume it's compliant with Ecma-48
    # (ISO/IEC-6429). (Lack of such support is extremely rare, and such
    # a case would tend to support setf rather than setaf.)
    color_prompt=yes
    else
    color_prompt=
    fi
fi

if [ "$color_prompt" = yes ]; then
    PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '
else
    PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ '
fi
unset color_prompt force_color_prompt

# If this is an xterm set the title to user@host:dir
case "$TERM" in
xterm*|rxvt*)
    PS1="\[\e]0;${debian_chroot:+($debian_chroot)}\u@\h: \w\a\]$PS1"
    ;;
*)
    ;;
esac

# enable color support of ls and also add handy aliases
if [ -x /usr/bin/dircolors ]; then
    test -r ~/.dircolors && eval "$(dircolors -b ~/.dircolors)" || eval "$(dircolors -b)"
    alias ls='ls --color=auto'
    #alias dir='dir --color=auto'
    #alias vdir='vdir --color=auto'

    alias grep='grep --color=auto'
    alias fgrep='fgrep --color=auto'
    alias egrep='egrep --color=auto'
fi

# colored GCC warnings and errors
#export GCC_COLORS='error=01;31:warning=01;35:note=01;36:caret=01;32:locus=01:quote=01'

# some more ls aliases
alias ll='ls -alF'
alias la='ls -A'
alias l='ls -CF'

# Add an "alert" alias for long running commands.  Use like so:
#   sleep 10; alert
alias alert='notify-send --urgency=low -i "$([ $? = 0 ] && echo terminal || echo error)" "$(history|tail -n1|sed -e '\''s/^\s*[0-9]\+\s*//;s/[;&|]\s*alert$//'\'')"'

# Alias definitions.
# You may want to put all your additions into a separate file like
# ~/.bash_aliases, instead of adding them here directly.
# See /usr/share/doc/bash-doc/examples in the bash-doc package.

if [ -f ~/.bash_aliases ]; then
    . ~/.bash_aliases
fi

# enable programmable completion features (you don't need to enable
# this, if it's already enabled in /etc/bash.bashrc and /etc/profile
# sources /etc/bash.bashrc).
if ! shopt -oq posix; then
  if [ -f /usr/share/bash-completion/bash_completion ]; then
    . /usr/share/bash-completion/bash_completion
  elif [ -f /etc/bash_completion ]; then
    . /etc/bash_completion
  fi
fi

 

    . restart-codekube.sh

 

#!/bin/bash
kubectl get pods "$HOSTNAME" || (
    echo "Use kubens to switch to the namespace of this instance and try again!"
    echo "(we can't do this for you since we don't know the namespace name)"
    exit 1
)
kubectl delete pod "$HOSTNAME"

 

    . code.sh

 

#!/bin/bash
# Script that mimics the open-from-stdin functionality of VSCode
if [ "$1" == "-" ]; then
    TEMP=$(mktemp /tmp/stdin_XXXXXX)
    cat > "$TEMP"
    exec code-server -r "$TEMP"
    exit 0
fi;

# Pass through everything else to `code-server`
# Shellcheck SC2068 = quoting variables to prevent globbing - we want that here.
# shellcheck disable=SC2068
exec code-server $@

 

    . startup.sh

 

#!/bin/bash
[[ -f /home/code/.homedir-initialized ]] || (
    echo "Remove this file to re-copy files from /etc/skel /opt/default_home at next container startup" > /home/code/.homedir-initialized
    # dotglob to catch files like `.bashrc`
    shopt -s dotglob
    cp -r /etc/skel/* /home/code
    cp -r /opt/default_home/* /home/code
    shopt -u dotglob
    # install kubernetes ext
    #su code --login -c "/usr/bin/code-server --install-extension ms-kubernetes-tools.vscode-kubernetes-tools"
)
# make workspace dir if it doesn't exist
[[ -d /home/code/workspace ]] || mkdir /home/code/workspace
# chown stuff to kube:kube
chown code:code /home/code -R
# generate env whitelist from su using.. a blacklist, pretty much.
env_whitelist=$(env | cut -d = -f 1 | grep -v -e HOSTNAME -e PWD -e HOME -e TERM -e SHLVL -e LC_ALL -e ^_$ | tr "\n" "," | head -c -1)
# configure kubectl so vscode's kubernetes extension works
# su code --login -w "$env_whitelist" -c "/usr/local/bin/generate-kubeconfig.sh"
# start code-server
# su code --login -w "$env_whitelist" -c "/usr/bin/code-server --bind-addr 0.0.0.0:8080 /home/code/workspace" # --enable-proposed-api [\"ms-vsliveshare.vsliveshare\",\"ms-vscode.node-debug\",\"ms-vscode.node-debug2\"]
runuser code --login -w "$env_whitelist" -c "/usr/bin/code-server --bind-addr 0.0.0.0:8080 /home/code/workspace" # --enable-proposed-api [\"ms-vsliveshare.vsliveshare\",\"ms-vscode.node-debug\",\"ms-vscode.node-debug2\"]

 

 

2. 설명

  ① Ubuntu 20.04를 기준으로 했다.

    . 18.04도 가능할 것으로 보이지만, `startup.sh` 내용 中 마지막 라인에 있는

    . `su` 또는 `runuser`의 `-w` 옵션이 18.04에서는 적용되지 않아서 지금은 20.04로 했다.

    → 18.04에서도 적용 가능하도록 연구해보겠다 (언제가 될지는...^^)

 

  ② 개발환경으로 사용되기에 기본적인 패키지들을 설치했다.

    . 추후 필요에 따라 추가하면 된다.

    . `DEBIAN_FRONTEND="noninteractive"` 부분이 없으면 설치 중간에 사용자 입력을 기다리기도 한다. (설치 오류)

 

  ③ Python3 설치 (pip 포함)

    . 일단 python3 개발환경으로 맞췄다.

    . 다른 언어 또는 라이브러리가 필요하다고 하면 자유롭게~

 

  ④ 한글 환경 설정 (locale)

    . 이 부분이 없으면 한글 처리에 문제가 발생한다.

    . 참고: 한글 지원되는 Ubuntu Docker Image 만들기

  ⑤ 사용자 계정 만들기 (code)

    . `code`라는 사용자 계정을 생성해서 이를 기준으로 맞추고자 했다.

    . 패스워드 없이 sudo 사용할수 있도록 했다.

    . `fixuid`를 이용해서 `code` 계정의 uid를 전체적으로 맞추도록 했다.

 

  ⑥ code-server 설치

    . 현재 시점의 최신 버전 `3.11.0`이 설치하도록 했다.

 

  ⑦ (예정) LiveShare 적용 준비

    . 지금은 아니지만, 나중에 LiveShare Extension 사용하도록 하기 위해 집어넣은 부분이다.

    . 아직은 분석이 필요한 단계

 

  ⑧ default home 준비

    . `code` 계정을 생성하면서 `/home/code` 디렉토리가 만들어졌는데,

    . 사용 중에 `/home/code` 디렉토리가 사라지면

    . 이를 다시 생성할 때 필요한 `.bashrc` 파일 같은 것을 넣어놓기 위한 과정이다.

 

  ⑨ 패스워드 및 포트 설정

    . `code-server` 접근할 때 필요로 하는 password를 지정하는 부분이다.

    . 외부에 노출되는 포트는 `8080`으로 했다.

 

  ⑩ 스크립트 복사

    . 필요에 따라 만들어진 스크립트들을 복사해 넣는 부분이다.

 

  ⑪ 실행

    . 실행 명령어 지정

 

 

3. build Image

  - 이미지 만들기는 다음과 같다.

    . 당연히 알겠지만, `-f Dockerfile` 부분은 생략 가능하다. (다른 파일명을 사용하는 경우에만 필요)

 

$ docker build -t code-server:v0.1 -f Dockerfile .

 

 

4. run Docker

  - Docker로 실행해 볼 수 있다

 

$ docker run -it -p 8080:8080 --name code -e PASSWORD="0000" code-server:v0.1

 

다행히 잘 동작한다.

 

 

반응형

'Work Flow'에 대해서 살펴보기 전에,
'Remote Repository'에 존재하는 'branch'와 'Local Repository'에 존재하는 'branch'의 관계에 대해서 알아보겠다.


조금 다른 일반적인(?) 용어로 이야기를 하자면,
서버에서 소스를 가져와서 작업을 하고 있던 중 서버의 내용이 변경이 되어,
이것을 내가 작업하고 있는 곳에 반영을 하고 싶은 경우에 어떻게 할 것인가? 에 대한 설명을 해보고자 한다.


1. branch -a

   - 현재 작업 공간을 한 번 점검해보도록 하겠다.



$ git branch -a


   - 오늘 진행할 내용을 위해서 잡다한 것 모두 지우고, 정리하고, push하고 해 놓았다.

   - 여기서 확인하고 싶은 것은 기본적인 branch의 내역이다. "origin/master"의 존재 !!



2. commit in master branch

   - local에서 즉, master에서 commit을 하나 해보자.



$ nano ./readme.txt
$ git commit -a -m "modify readme.txt in master br"
$ git status


   - 여기에서 잘 살펴볼 부분은 [ git status ]를 했을 때 나오는 메시지이다.
   - "Your branch is ahead of 'origin/master' by 1 commit."
   - 최근의 git은 정말 안내 메시지가 너무 잘 되어 있다~!!! 짱~!!!


3. commit in origin/master

   - remote repository에 commit을 하나 추가된 상황을 만들고자 한다.




$ cd /srv/workspace/2nd
$ git clone {계정}@localhost:/srv/repository/bare1repo
$ cd ./bare1repo


   - 별도의 commit을 만들어 remote에 넣기 위해서 다른 곳에 별도의 local repository를 clone 하자


$ nano ./readme1.txt
$ git commit -a -m "modify readme1.txt in master br, but other master"
$ git push


   - 파일 하나를 수정하고 commit 한 다음에, remote repository로 밀어넣자(push).



4. fetch & merge

   - remote repository의 변경된 내역을 local로 받아오기 위한 작업을 해보자.



$ git fetch
$ git status

   - remote repository의 정보를 얻어오기 위한 명령어는 [ git fetch ]이다.
   - [ git status ]를 해보면 이전과는 또 다른 메시지가 보일 것이다.

   - " Your branch and 'origin/master' have diverged,
        and have 1 and 1 different commit each, respectively. "

   - " diverge " 뜻을 모르는 저같은 분들을 위한 단어의 의미 :
1. (다른 방향으로) 갈라지다   2. 나뉘다, 갈리다   3. (예상・계획 등에서) 벗어나다


$ git merge origin/master

   - [ git log ]를 보면, 위의 그림대로 구성되어진 것을 확인할 수 있을 것이다.




별 것 아닌 것으로 보일 수도 있는데,
git을 혼자서가 아니라 팀으로 작업하는 경우라면 의외로 자주 발생하는 상황일 것이다.

Git에서 보여주는 메시지들을 다시 한 번 잘 살펴보고, 흐름을 잘 느끼고 생각하면 많은 것을 배울 수 있을 것이다.



이런 에잇~ 또 12시를 넘겨버렸네.... ㅠㅠ
오늘 자전거 타이어 바꾸려고 편도 15km가 넘는 거리를 달려갔지만 결국 허탕치고 오늘 자전거만 30km가 넘게 타서...
지금 허리아프고 손목아프고, 목 아프고..... 이런 상황에서 12시를 넘겨버리다니... ㅠㅠ
내일 출근해야하는데.... 흑흑.... 어여 잠자야겠다.

반응형

세입자의 설움으로 전셋집 옮기고 체력고갈,
더불어 진급자 회식 및 결혼 예비 후배들과의 회식들로 인한 추가 체력고갈...
그리고 마지막으로 안또라이들 학습.... 그리고 결정적인 귀차니즘으로 또 다시 오랜만에 찾아온 Git... ^^

조금 더 공부하고 조금 더 분석해야하는데, 그게 말처럼 쉽지가 않다.... 월급쟁이의 비애라고하면 변명이겠지!? ^^


오늘은 remote repository에 대해서 조금 더 알아보고자 한다.


$ git clone /srv/repository/BareRepo.git
$ cd ./BareRepo
$ git remote
$ git remote -v

[ git remote ]라는 명령어는 어떨 때 사용하는걸까!?
어떤 repository의 어떤 branch를 사용하고 있는지 알기 위해서 또는 관리를 위해서 사용하는 명령어이다.

만약 여러 repository를 사용할 경우 그 리스트도 주르륵 보여준다.


여기에서 당연히 의문을 가져야 한다!!!
"여러 repository를 사용"한다고?!

 

$ git remote add other /srv/repository/otherRepo.git
$ git remote
$ git remote -v

이미 "BareRepo.git"을 가져온 상태에서, 그 안에서 [ git remote add ]를 통해서 다른 repository를 가져온 것이다.
'other'라는 것은 임의로 해당 repository를 지칭하는 별명을 지어준 것이다.

본래 있던 것은 'original'이라는 이름이고, 새로 추가한 것은 'other'라는 이름이다.


그러면, 여기에서 또 하나의 의문이 생겨야 한다.

하나의 공간에 2가지의 것이 같이 있으면, 지금 작업하고 있는 것이 어떤 것에 속하는지 어떻게 알려줄까?


$ git fetch other

아직 branch에 대해서 알아보지 않았으므로 이에 대한 설명은 뒤로 넘기겠다.

여하튼, [ git fetch ]라는 명령어를 이용하여 두 가지를 오락가락 할 수 있다!
그런데, 지금 "otherRepo.git"이라는 repository를 넣었다고 했는데 그 파일들은 어디에 있을까?!

지금 사용하고 있는 "otherRepo.git" repository에 들어있는 파일은 "readme.txt"이다.
그런데, "BareRepo.git" repository에도 같은 이름의 파일이 있다.
"혹시 그래서 뭔가 충돌이 난 것은 아닐까?!"라는 생각이 들었다.

그래서, 응급으로 "otherRepo.git"에 "other.txt" 파일을 push해 넣었다.
그런 후 다시 fetch를 해보았다.


다시 fetch를 했음에도 파일 내용은 바뀐 것이 없다.


이 즈음해서 아! 내가 변경 사항을 받아오는 것에 대해서 살펴보지 않았구나~!!!라는 생각이 번뜩!
그래서 바로 직전 글 [ git pull ]에 대해서 블로깅을 했다!!!!


$ git pull
$ git pull other master

그냥 [ git pull ]을 하게 되면 뭔가 받아오는데, 우리가 새로 추가한 repository, otherRepo의 자료는 보이질 않는다.
그러면 어떻게 해야 otherRepo의 내용을 받아올 수 있을까?!

[ git pull other master ]라고 하면 된다.
그런데, 위의 스크린샷을 보면 알겠지만 'CONFLICT'가 발생을 했다.

앞에서도 말했지만, 두 개의 repository에 'readme.txt' 파일이 똑같은 이름으로 존재하고있다.
그래서 충돌이 난 것이다.
보통은 git이 똑똑하게 자동으로 merge를 해주기도 하는데, 위의 경우엔 그것도 실패한 경우이다.



이번 블로그에서는 뭘 배우는 것이 아니라,
앞으로 무엇을 봐야할 지에 대해서 확인하고자 하는 블로깅이다.

[ git pull other master ]라는 명령어에서 'master'라는 것이 무엇인고 하니, 바로 branch 이름이다.
앞으로 branch에 대해서 살펴보도록 하겠다.

그 다음엔 위의 경우처럼 merge를 하는 경우에 대한 것이다.
repository를 여러개를 사용할 경우도 있지만, 주로 서로 다른 branch에서 하나로 merge하는 경우가 더 많을 것이다.


앞으로 하나씩 더 알아가 보도록 하자.

반응형

'SCM > Git-GitHub' 카테고리의 다른 글

Git Branch (브랜치) - Local Ⅰ (branch 생성, HEAD)  (0) 2012.04.12
Pro Git 번역본  (0) 2012.03.22
업데이트 - git pull, 중간 정리  (0) 2012.03.17
Remote Repository - git push  (2) 2012.03.04
Git Server - push + 한글  (1) 2012.02.26

+ Recent posts