dd로 disk 전체 백업하기

$ sudo apt-get install ntfs-3g
$ sudo fdisk -l
$ sudo mkdir /mnt/sdb5 && sudo mount.ntfs-3g /dev/sdb5 /mnt/sdb5
$ sudo dd if=/dev/sdc of=/mnt/sdb5/IMAGE_NAME_HERE.img bs=64K status=progress

미니 PC를 하나 샀다. SATA M.2 SSD 안에 Windows 10 Pro 정품이 깔려 있다. 이미지로 만들어서 백업하고 우분투 깔아야겠다.

[Docker] docker in docker의 Permission denied 문제

도커 컨테이너 안에서 도커를 사용하는 방법은 Host의 /var/run/docker.sock를 컨테이너에서 bind mount하면 된다. 쉽게 설명해 docker run 할 때 아래처럼 -v /var/run/docker.sock:/var/run/docker.sock 옵션을 주면 된다는 뜻이다. 물론 컨테이너 안에는 도커가 설치되어 있어야 한다.

docker run -it --name ubuntu -v /var/run/docker.sock:/var/run/docker.sock ubuntu:20.04

이렇게 하면 도커 컨테이너 안에서 /var/run/docker.sock의 소유자가 root:docker 로 생기는데 이때의 그룹 id는 호스트의 그룹 id 값을 따르게 된다. 내 맥에서는 docker 그룹의 gid가 134이고, ubuntu 컨테이너의 docker 그룹의 gid는 1000이다.

$ cat /etc/group | grep docker # Host에서..
docker:x:134:dasomoli

컨테이너 안에서 /var/run/docker.sock를 살펴보면 아래처럼 소유자가 root:134 이다.

root@ce1351052f58:/# ls -l /var/run/docker.sock
srw-rw---- 1 root 134 0 Dec 21 13:19 /var/run/docker.sock

그러나 컨테이너 내에서 도커 설치 후 docker 그룹의 gid는 호스트의 gid인 134가 아닌 컨테이너 내부 환경에서 주어진다. 아래에서는 999이다.

root@ce1351052f58:/# cat /etc/group | grep docker
docker:x:999:

따라서 컨테이너 내부에서 root가 아닌 일반 유저로 도커를 사용하려고 하면 아래처럼 Permission denied 에러가 발생하게 된다.

$ id
uid=1000(dasomoli) gid=1000(dasomoli) groups=1000(dasomoli)

$ docker ps -a
Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get "http://%2Fvar%2Frun%2Fdocker.sock/v1.24/containers/json?all=1": dial unix /var/run/docker.sock: connect: permission denied

이 문제의 해결 방법으로 사람들이 이야기하는 방법은 chown으로 컨테이너 내부에서 owner를 root:docker 로 바꾸고 사용하는 방법, 또는 chmod로 아예 a+rw 를 주는 방법을 이야기하는데, chown으로 owner를 바꾸면 컨테이너 외부의 호스트 파일의 소유자 정보도 바뀌는 문제가 있다. 위의 docker의 gid가 컨테이너에서는 999, 호스트에서는 134인 경우에 컨테이너에서 chown root:docker를 해보면 호스트에서 gid가 999인 그룹에 속한 파일로 나온다. 즉, 호스트의 도커 실행 환경에 문제가 생긴다.

$ ls -l /var/run/docker.sock
srw-rw---- 1 root systemd-coredump 0 12월 21 22:19 /var/run/docker.sock # docker가 아니고 systemd-coredump 그룹 소유로 바뀌었다!!

$ cat /etc/group | grep systemd-coredump
systemd-coredump:x:999:

따라서 이 방법보다는 둘 모두의 docker 그룹의 gid를 맞춰주는 방법이 더 낫다. 컨테이너 안에서 groupmod로 다음을 실행한다. 아래에서 134는 호스트에서의 docker 그룹의 gid이다.

root@ce1351052f58:/# groupmod -g 134 docker

root@ce1351052f58:/# chown root:docker /var/run/docker.sock # 컨테이너가 실행 중이었다면 owner를 바꾼다.

root@ce1351052f58:/# ls -l /var/run/docker.sock
srw-rw---- 1 root docker 0 Dec 21 22:19 /var/run/docker.sock

호스트에서도 확인해보자.

$ ls -l /var/run/docker.sock
srw-rw---- 1 root docker 0 12월 21 22:19 /var/run/docker.sock

도커 이미지를 빌드할 때 Dockerfile 내에서 아예 먼저 해준다면, 실행 시에 따로 해주지 않아도 된다.

# Dockerfile 안의 내용
ARG HOST_DOCKER_GID="134"

RUN groupmod -g ${HOST_DOCKER_GID} docker

위의 Dockerfile로 도커 이미지를 빌드할 때는 다음과 같은 방식으로 넘겨도 된다.

$ docker build --build-arg HOST_DOCKER_GID=$(stat -c "%g" /var/run/docker.sock) -t ubuntu20.04

위에서 사용한 호스트에서 docker 그룹의 gid를 얻는 방법은 “[Linux/Mac] group id 얻기” 글을 참조한다. 호스트와 컨테이너 둘 간의 gid 충돌은 유의하자.

[Docker] docker commands

실행 중인 docker process (machine) 보기

docker ps

실행 중 + 실행 중이 아닌 docker process 보기

docker ps -a

docker 이미지 보기

docker images

docker process 삭제

docker rm -rf [container name]

docker 이미지 삭제

docker rmi [image name]

docker 이미지 가져오기

docker pull [image name]

docker process 시작

docker start [container name]

docker process 중지

docker stop [container name]

실행 중인 모든 컨테이너 강제 종료

docker kill $(docker ps -q -f status=running)

실행 중인 모든 컨테이너 중지

docker stop $(docker ps -q -f status=running)

종료된 모든 컨테이너 삭제

docker rm $(docker ps -q -f status=exited)

시스템 상의 모든 이미지 삭제

docker image rm -f $(docker image ls -q)

docker 로그 보기

docker logs [container name]

docker network 삭제

docker network prune -f

alias해서 간편히 사용하기

alias dockerkill='docker kill $(docker ps -q -f status=running)'
alias dockerstop='docker stop $(docker ps -q -f status=running)'
alias dockerrm='docker rm $(docker ps -q -f status=exited)'
alias dockerimgrm='docker image rm -f $(docker image ls -q)'
alias dockernetprune='docker network prune -f'

docker cli 실행

$ docker exec -it cli /bin/bash

[HTML5&CSS] 멀티미디어 넣기

오디오

웹페이지 내에 오디오를 넣고 싶을 때는 audio element로 넣을 수 있다. src attribute 혹은 source element로 하나의 오디오 소스를 가지거나 audio element의 children으로 source element 리스트를 넣어서 여러개의 오디오 소스를 가질 수 있다.

<audio controls src="media/dasomoli.mp3">여러분의 브라우저가 audio 태그를 지원하지 않는 것 같네요..</audio>

위처럼 <audio>와 </audio> 사이에 브라우저가 지원하지 않을 때 나타낼 메시지를 넣을 수 있다. controls attribute는 여러분이 오디오를 재생할 수 있도록 할 수 있다. 다음과 같은 contol이 나타난다.

다음과 같은 속성들이 있다.

  • autoplay (boolean)
  • preload (none / metadata / auto)
  • loop (boolean)
  • controls

autoplay는 전부 다운로드 받지 않더라도 재생이 가능할만큼만 되면 바로 재생한다. 사람들이 웹페이지에 들어왔을 때 오디오가 바로 재생되면 싫어하므로 사용에 주의하라.

preload는 미디어 소스의 로딩을 어떻게 할지를 정하고 싶을 때 사용한다. none은 preload하지 않고, metadata는 metadata만 로드한다. auto는 empty string(“”)과 동등한데, 전체 파일이 로드된다.

loop는 반복 재생하도록 한다.

controls는 브라우저의 기본 미디어 컨트롤을 추가한다. 사용자가 오디오의 재생을 제어할 수 있다. 브라우저마다 UI가 다른데, 공통적인 기능은 비슷하다. UI가 다르므로 controls attribute를 셋팅하지 않고 HTML, CSS, Javascript를 사용해서 customize한 control을 생성, 원하는 디자인을 할 수도 있다.

webm, mp3, ogg등 브라우저마다 지원하는 format이 다르다. 이에 대해서는 MDN의 다음 글을 참고하자.

여러개의 source를 넣고 싶을 때는 source element를 이용한다. src attribute를 사용하지 않고 여러개의 source를 사용했음에 주목하라. 이 중 지원하지 않는 format이 있으면 다음 것을 시도한다.

<audio controls>
  <source src="media/dasomoli.webm" type="audio/webm">
  <source src="media/dasomoli.mp3" type="audio/mp3">
  <source src="media/dasomoli.ogg" type="audio/ogg">
  여러분의 브라우저가 <code>audio</code>를 지원하지 않는 것 같아요!
</audio>

동영상 (Video)

video element와 audio element는 둘 모두 HTML media elements이다. 사실 video element로 audio를, audio element로 video를 재생하는 것도 가능하다. video element는 display 영역을 제공한다는 것이 차이이다.

video element의 attribute는 audio element 것을 모두 가진다. 추가로 다음 attribute를 제공한다:

  • height
  • width
  • poster

width와 height attribute는 video display area의 width와 height을 각각 조정한다. 둘 모두 pixel로 조정된다. %로 비율을 쓸 수 없다.

poster attribute는 video가 다운로드되는 동안 보여줄 이미지를 지정한다. 지정하지 않으면 video의 첫 frame의 다운로드 전에는 빈 네모가 보이고, 첫 frame을 다운로드 받으면 그 첫 frame이 보일 것이다.

Text track

track element는 media element와 연관된 시간 기준의 글을 지정한다. 이는 미디어 재생과 싱크가 맞는 시간에 어떤 글을 보여줄 수 있다는 뜻이다. 자막이나 해당 미디어에 대한 설명은 물론, 앞이 안보이거나 소리가 안들리는 사람들에게도 어떤 것인지 설명할 수 있도록 해준다.

video의 source element와 같이 하나의 media element 에 여러개의 track element를 넣어서 그 media에 대한 여러 track을, 예를 들면 다른 언어 자막 같은 식으로 제공할 수 있다.

track element의 attribute는 다음과 같다:

  • src: text track file의 위치
  • default: media element 당 하나의 track element가 default track으로 지정될 수 있다. 사용자 설정에 따라 override될 수 있다.
  • kind: text track이 무엇으로 사용되는지를 지정한다. subtitles, captions, descriptions, chapters, metadata같은 여러 옵션이 있다. default는 subtitles이다.
  • srclang: track text의 언어. 영어는 en, 프랑스어는 fr. subtitle track이면 srclang은 필수다.
  • label: captions과 subtitles 사이를 가르는데 사용되는 제목
<track src="media/dasomoli-ko.vtt" kind="subtitle" label="Korean subtitles">
<track src="media/dasomoli-en.vtt" kind="subtitle" label="English subtitles">
<track src="media/dasomoli-fr.vtt" kind="subtitle" label="French subtitles">

자막에 공용적으로 많이 쓰이는 format은 Web Video Text Tracks Format (WebVTT)이다. 이 format은 timestamps와 captions를 설명하는 plain text로 구성된다. 다음과 같은 형식이다.

WEBVTT
00:00:05.000 --> 00:00:10.000
5 seconds
00:00:15.000 --> 00:00:20.000
15 seconds

이미지

여러 방법이 있다:

  • img element
  • picture element
  • 프로그래밍한 그래픽

img element는 가장 간단하게 img를 넣는 방법이다. src로 파일 위치를 지정한다. alt attribute는 img가 나타나지 않을 때 해당 이미지에 대한 설명을 제공한다. 다음과 같이 사용한다

<img src="media/dasomoli.png" alt="Genius developer">

picture element는 img와 비슷한데 여러개의 source element를 가지고 그 중 어느 것을 나타낼지에 대한 rule을 정한다. 다음처럼 쓴다.

<picture>
    <source srcset="media/dasomoli-small.png" media="(max-width: 639px)">
    <source srcset="media/dasomoli-large.png" media="(max-width: 800px)">
    <img src="media/dasomoli.png" alt="Geniuse developer">
</picture>

위에서 source element는 media attribute를 갖는다. 위 코드는 첫번째 것부터 media attribute가 참인지를 보고 맞다면, 위 코드에서는 viewport가 639 픽셀 이하인지를 보고 맞다면 해당 이미지를 보여준다. 아니라면 다음 것으로 넘어간다. 다 안맞으면 마지막의 img의 것을 보여주게 된다. 브라우저가 picture를 지원하지 않을 때도 picture의 가장 마지막 것을 보여주게 된다.

조건으로 media 외에도 type attribute나 mime type도 사용할 수 있다.

위의 .jpeg, .gif, .png, .webp 같은 foramt외에도 SVG (Scalable vector graphics)나 canvas element 처럼 프로그래밍한 그래픽을 생성할 수 있다. SVG는 vector graphics를 위한 XML 기반의 format이고, canvas element는 웹페이지 상에서 rasterized graphics를 생성하는데 사용되는 JavaScript drawing API로 접근 할 수 있는 element다.

svg element

svg는 vector graphics를 정의하는 XML 기반 format이다. Vector graphics는 깨지는 문제없이 비율에 따라 계산되기 때문에 반응형 웹에 매우 유용하다. 간단한 예로 play와 stop button을 만든다고 하자.

<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" width="100" height="100">
    <circle cx="50" cy="50" r="50" fill="black" />
            <path d="M 90,50 25,80 25,20 z" fill="white" />
</svg>
<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" width="100" height="100">
    <circle cx="50" cy="50" r="50" fill="black" />
    <path d="M 25,25 75,25 75,75 25,75 z" fill="white" />
</svg>

viewBox attribute로 x좌표 0, y좌표 0에서 100 dimension으로 설정했다. viewBox는 pixel로 표시하지 않는다. width와 height attribute로 비율을 정할 수 있다. 안에 들어가는 children들은 viewBox의 상대적 위치에 놓이게 된다.

circle element로 x좌표 50, y좌표 50의 위치에 반지름 50짜리 원을 그렸고, 안을 black으로 채웠다. hex value #rrggbb로도 당연히 설정 가능하다. 그 후 path로 3점을 정해서 삼각형을 하나 그리고 이를 white로 채웠다. 비슷하게 stop 버튼은 사각형을 하나 그리고 이를 white로 채웠다. 위 소스는 다음과 같이 렌더링된다.

svg는 canvas처럼 javaScript가 필요하지 않고 바로 접근 가능하지만, shape들이 많으면 성능 문제가 일어날 수 있다.

canvas Element

canvas element로는 rasterized graphics를 렌더링할 수 있다. 이를 위해서 JavaScript의 drawing API를 사용한다. 2D와 WebGL의 두가지 렌더링 모드가 있다. WebGL은 GPU acceleration과 같은 shader support를 제공한다.

browser가 canvas를 지원하는지를 확인한 후 이용하는 것이 좋다. 확인하는 코드는 다음과 같이 쓸 수 있다.

<canvas id="canvasArea" width="640" height="480">
    여러분의 브라우저가 <code>canvas</code>를 지원하지 않네요.
</canvas>
<script>
    const canvas = document.getElementById('canvasArea');
    if (canvas.getContext) {
            const context = canvas.getContext('2d');
            // 여기다가 뭔가를 그려봅시다.
    }
</script>

선 그리기

moveTo(x, y) 로 옮기고, lineTo(x, y) 로 경로를 정한 후, strokeStyle을 정한 후 stroke()로 외곽선을 그린다. lineTo로 이어서 그린 후 해당 경로를 fillStyle로 정한 후 fill()로 채울 수도 있다.

사각형(Rectangle) 그리기

속이 빈 사각형을 외곽선 만으로 그리고 싶으면, strokeStyle로 외곽선의 style을 정하고, lineWidth로 외곽선 굵기를 정한 후, strokeRect(x, y, width, height)로 그린다.

안이 채워진 사각형을 그리고 싶으면 fillStyle로 style을 정하고, fillRect(x, y, width, height)로 그린다. fillStyle은 CSS에서 사용하는 값이면 다 쓸 수 있다. color, backgroundColor같은 property나 black, red, white 같은 color값, hex value #rrggbb나, rgba(25, 35, 45, 0.7) 같은 rgba 값도 가능하다.

외곽선과 안이 채워진 것을 모두 적용하고 싶다면, strokeStylefillStyle을 모두 설정하고, rect(x, y, width, height)로 사각형 경로를 설정하고, fill()로 채우고, stroke()로 외곽선을 그리면 된다.

context.strokeStyle = "blue";
context.lineWidth = 5;
context.strokeRect(50, 50, 50, 50);
context.fillStyle = "green";
context.fillRect(100, 100, 200, 150);
context.fillStyle = "red";
context.strokeStyle = "lime";
context.lineWidth = 4;
context.rect(300, 50, 50, 50);
context.fill();
context.stroke();

위의 코드는 아래와 같이 렌더링된다.

원 (Circle) 그리기

arc(x, y, radius, startangle, endangle, anticlockwise)로 그린다. x와 y는 원의 중심, radius는 반지름, startangle과 endangle은 시작과 끝 각, anticlockwise는 true이면 반시계방향, false이면 시계방향이다. 각도는 radian값이다.

context.fillStyle = 'red';
context.arc(100, 100, 40, 0, Math.PI * 2, false);
context.fill();
context.beginPath();
context.fillStyle = 'orange';
context.arc(200, 100, 40, 0, Math.PI * 2, false);
context.fill();
context.beginPath();
context.fillStyle = 'green';
context.arc(300, 100, 40, 0, Math.PI * 2, false);
context.fill();

위 코드는 아래처럼 렌더링된다. 새로운 style을 적용하기 위해서 beginPath()를 썼음에 주의하라

canvas 지우기

clearRect(x, y, width, height) 으로 원하는 영역을 지울 수 있다. 전체를 지우고 싶으면 아래처럼 해당 canvas의 width와 height으로 지우면 된다.

context.clearRect(0, 0, canvas.width, canvas.height);

[Mac] 화면 캡쳐 방법

전체 스크린샷 캡쳐: Shift + command + 3
화면 일부 캡쳐: Shift + command + 4
윈도우 또는 메뉴 캡처 방법: Shift + command + 4 + space

캡쳐한 이미지는 미리보기 앱을 사용해서 png와 같은 그림 파일로 저장 가능하다.

https://support.apple.com/ko-kr/HT201361

[HTML5&CSS] Dark theme 만들기

다크 테마를 만들기 위해 색상을 다뤄보자.

테마 내의 새로운 HTML element를 몇 개 알고 넘어가자.

  • pre (preformatted): HTML 파일 내에 whitespace를 포함하여 적힌 그대로 보여준다. 일반적으로 monospace font, 즉 고정폭 폰트로 보여준다.
  • abbr (abbreviation): acronym이나 abbreviation을 나타낸다. acronym element는 deprecated되었다. 그렇지만, 하위 호환성을 위해 포함된다.

새로운 CSS background properties도 몇 개 알고 넘어가자.

  • background-image: element의 배경 이미지. url()에 이미지 URL을 넣는다.
  • background-repeat: 배경 이미지를 어떻게 반복할지. 다음 값들을 사용할 수 있다.
    • repeat: 모든 공간을 덮을만큼 반복한다. 잘릴 수 있다.
    • space: 잘림 없이 가능한만큼 반복한다. 비율이 유지되고, 첫번째와 마지막 이미지 사이의 가장자리를 잡기 위한 여백이 공간을 채우기 위해서 바뀐다.
    • round: 이미지가 늘어나거나 줄어들어서 공간을 채운다.
    • no-repeat: 이미지가 반복되지 않는다.

색상 반전시키기

반대 색상을 찾기 위해서 https://www.colortools.net을 이용하자. Opposite Color Tool을 이용하면 반대 색상을 쉽게 얻을 수 있다. 반전시킨 색상을 각 element에 적용한다.

 

HSL function 사용하기

HSL function은 세가지 값으로 색을 만든다. Hue, Saturation, Lightness.

  • H는 색상(Hue)를 나타낸다. 색상환(color wheel)에서 각도를 나타낸다. degree로 나타내던가 또는 radian으로 지정한다. 단위 없이 쓰면 degree이고, 0이 pure red, 120이 pure green, 240이 pure blue이다.
  • S는 채도(Saturation)을 나타낸다. 100% saturation은 완전히 짙은 색, 0%는 완전히 흐린 색, 회색이다. 50%가 “normal” color이다.
  • L은 밝기(lightness)를 나타낸다. 100%는 하얀색, 0%는 검정색이 된다.

따라서 색상을 180 degree 돌리면 반대색이 된다. 회색을 반전시키고 싶을 때는 밝기를 뒤집으면 된다. 회색을 얻고 싶으면 채도를 0으로 바꾸면 된다. 여기서 grayscale을 바꾸고 싶으면 밝기를 바꾸면 된다.

 

CSS Invert Filter

filter: invert() 를 사용해서 뒤집을 수도 있다.