Docker Multi-Architecture Build Guide

Docker 이미지 다중 아키텍처(Multi-Architecture) 빌드 가이드 Docker build Docker 이미지를 빌드할 때는 기본적으로 빌드하는 머신의 CPU 아키텍처(Platform)에 맞춰 빌드됩니다. 이는 Docker의 기본 동작이며, 호스트 시스템의 아키텍처와 일치하는 이미지를 생성합니다. 아키텍처의 중요성: 컨테이너는 호스트 OS의 커널을 공유하지만, CPU 아키텍처에 맞는 바이너리가 필요합니다. 예를 들어, ARM64용으로 빌드된 이미지는 AMD64 시스템에서 직접 실행할 수 없습니다. macOS arm64 테스트 $ uname -a Darwin glass 20.6.0 Darwin Kernel Version 20.6.0: Wed Jun 23 00:26:27 PDT 2021; \ root:xnu-7195.141.2~5/RELEASE_ARM64_T8101 arm64 # Dockerfile FROM alpine RUN uname -a # no-cache, plain output $ docker build . -t cdecl/alpine --no-cache --progress=plain ... #5 [2/2] RUN uname -a #5 sha256:bb35af1757e6b002e99344411e8e8fc700e8760f29f48b4de0f0bb7276ead75d #5 0.238 Linux buildkitsandbox 5.10.25-linuxkit #1 SMP PREEMPT Tue Mar 23 09:24:45 UTC 2021 aarch64 Linux #5 DONE 0.2s ... $ docker image inspect cdecl/alpine -f '{{.Architecture}}' arm64 Platform 변경하여 이미지 빌드 Docker는 --platform 플래그를 통해 타겟 아키텍처를 지정할 수 있습니다. QEMU를 통한 에뮬레이션으로 크로스 플랫폼 빌드가 가능합니다. ...

2021년 8월 30일 · Byung Kyu KIM

CryotoPP Example

CryptoPP https://www.cryptopp.com/{:target="_blank"} Crypto++ 사용하기, 예제{:target="_blank"} 암호화 지식 (개발자){:target="_blank"} 기존 작성한 내용(5.6 버전)의 최신화(8.5 버전) : 빌드 이슈 Package 설치 vcpkg 사용 : 8.5.0 $ ./vcpkg install cryptopp Computing installation plan... The following packages will be built and installed: cryptopp[core]:arm64-osx -> 8.5.0 ... The package cryptopp:arm64-osx provides CMake targets: find_package(cryptopp CONFIG REQUIRED) target_link_libraries(main PRIVATE cryptopp-static) CMakeLists.txt cmake_minimum_required(VERSION 3.11) project(main) set(CMAKE_CXX_STANDARD 17) add_executable(main main.cpp) target_compile_options(main PRIVATE -Wall -O2) find_package(cryptopp CONFIG REQUIRED) target_link_libraries(main PRIVATE cryptopp-static) Build $ mkdir build && cd build $ cmake .. -DCMAKE_TOOLCHAIN_FILE=<PATH>/vcpkg/scripts/buildsystems/vcpkg.cmake $ build Example 기본 Flow - Encryption : StringSource -> StreamTransformationFilter(Encryptor) -> Base64Encoder(StringSink) - Decryption : StringSource -> Base64Decoder -> StreamTransformationFilter(Decryptor, StringSink) 과거 버전과의 이슈 std::byte의 표준화 이전에 작성된 라이브러리라, byte 타입 충돌 https://www.cryptopp.com/wiki/Modes_of_Operation{:target="_blank"} KEY, IV 를 정의하기 위해 CryptoPP::SecByteBlock 타입 사용 #include <iostream> #include <algorithm> using namespace std; #include <cryptopp/cryptlib.h> #include <cryptopp/base64.h> #include <cryptopp/aes.h> #include <cryptopp/seed.h> #include <cryptopp/des.h> #include <cryptopp/modes.h> #include <cryptopp/filters.h> template <class EncryptorType> std::string Encrypt(EncryptorType &encryptor, const std::string &PlainText) { std::string CipherText; CryptoPP::StringSource(PlainText, true, new CryptoPP::StreamTransformationFilter( encryptor, new CryptoPP::Base64Encoder(new CryptoPP::StringSink(CipherText), false) /* default padding */ ) ); return CipherText; } template <class DecryptorType> std::string Decrypt(DecryptorType &decryptor, const std::string &EncText) { std::string PlainText; CryptoPP::StringSource(EncText, true, new CryptoPP::Base64Decoder( new CryptoPP::StreamTransformationFilter( decryptor, new CryptoPP::StringSink(PlainText) ) ) ); return PlainText; } int main() { using namespace std; using AES = CryptoPP::AES; CryptoPP::SecByteBlock KEY(AES::DEFAULT_KEYLENGTH); CryptoPP::SecByteBlock IV(AES::DEFAULT_KEYLENGTH); // 임의 값 초기화 for (auto &c : KEY) c = 0; for (auto &c : IV) c = 0; CryptoPP::CBC_Mode<AES>::Encryption Encryptor { KEY, KEY.size(), IV }; CryptoPP::CBC_Mode<AES>::Decryption Decryptor { KEY, KEY.size(), IV }; try { string sText = "Plain Text"; string sEnc, sDec; sEnc = Encrypt(Encryptor, sText); cout << sText << " -> " << sEnc << endl; sDec = Decrypt(Decryptor, sEnc); cout << sEnc << " -> " << sDec << endl; } catch (exception &ex) { cerr << ex.what() << endl; } return 0; } $ ./main Plain Text -> MtiafY0csWZJZzsRNfE8cA== MtiafY0csWZJZzsRNfE8cA== -> Plain Text

2021년 8월 28일 · Byung Kyu KIM

GCC 설치 (`macOS`, `Windows`)

macOS 및 Windows 에 GCC 설치하기 MAC OS brew : macOS 용 패키지 관리자 https://brew.sh/index_ko{:target="_blank"} brew 사용 gcc 설치 Command line tools 설치 xcode 없이 개발툴 설치 $ xcode-select --install clang 이 설치되고 gcc로 심볼링 링크 걸려 있음 $ gcc -v Configured with: --prefix=/Library/Developer/CommandLineTools/usr --with-gxx-include-dir=/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/4.2.1 Apple clang version 12.0.5 (clang-1205.0.22.11) Target: arm64-apple-darwin20.6.0 Thread model: posix InstalledDir: /Library/Developer/CommandLineTools/usr/bin GCC (G++) 설치 # 특정 버전으로 설치 가능 $ brew search gcc ==> Formulae gcc gcc@5 gcc@8 libgccjit ghc ncc gcc@10 gcc@6 gcc@9 x86_64-elf-gcc scc gcc@4.9 gcc@7 i686-elf-gcc grc tcc ==> Casks gcc-arm-embedded # 기본(최신) 버전 설치 $ brew install gcc ==> Auto-updated Homebrew! Updated 1 tap (homebrew/core). ==> Updated Formulae Updated 1 formula. ==> Downloading https://ghcr.io/v2/homebrew/core/gcc/manifests/11.2.0 Already downloaded: /Users/cdecl/Library/Caches/Homebrew/downloads/210783e77b227b8210d559abfe3514cdb95c915619fa3f785ad212120d6a36f9--gcc-11.2.0.bottle_manifest.json ==> Downloading https://ghcr.io/v2/homebrew/core/gcc/blobs/sha256:23ec727fa684a9f65cf9f55d61d208486d5202fb6112585a01426a Already downloaded: /Users/cdecl/Library/Caches/Homebrew/downloads/8d1fae8a356d50aa911004b768eff64c241e170ce9be66e684b819fc4f67fc7c--gcc--11.2.0.arm64_big_sur.bottle.tar.gz ==> Pouring gcc--11.2.0.arm64_big_sur.bottle.tar.gz 🍺 /opt/homebrew/Cellar/gcc/11.2.0: 1,412 files, 339.5MB 심볼릭링크 설정 및 PATH 설정 $ cd /opt/homebrew/Cellar/gcc/11.2.0 $ ls -l ... -rwxr-xr-x 1 cdecl admin 1.7M 8 28 13:41 g++-11 -rwxr-xr-x 1 cdecl admin 1.7M 8 28 13:41 gcc-11 ... $ ln -s g++-11 g++ $ ln -s gcc-11 gcc .zshrc or .bashrc export PATH=/opt/homebrew/Cellar/gcc/11.2.0/bin:$PATH $ g++ -v Using built-in specs. COLLECT_GCC=g++ COLLECT_LTO_WRAPPER=/opt/homebrew/Cellar/gcc/11.2.0/libexec/gcc/aarch64-apple-darwin20/11.1.0/lto-wrapper Target: aarch64-apple-darwin20 Configured with: ../configure --prefix=/opt/homebrew/Cellar/gcc/11.2.0 --libdir=/opt/homebrew/Cellar/gcc/11.2.0/lib/gcc/11 --disable-nls --enable-checking=release --enable-languages=c,c++,objc,obj-c++,fortran --program-suffix=-11 --with-gmp=/opt/homebrew/opt/gmp --with-mpfr=/opt/homebrew/opt/mpfr --with-mpc=/opt/homebrew/opt/libmpc --with-isl=/opt/homebrew/opt/isl --with-zstd=/opt/homebrew/opt/zstd --with-pkgversion='Homebrew GCC 11.2.0' --with-bugurl=https://github.com/Homebrew/homebrew-core/issues --build=aarch64-apple-darwin20 --with-system-zlib --disable-multilib --with-native-system-header-dir=/usr/include --with-sysroot=/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk Thread model: posix Supported LTO compression algorithms: zlib zstd gcc version 11.1.0 (Homebrew GCC 11.2.0) Windows chocolatey chocolatey : Windows 용 패키지 관리자 https://chocolatey.org/{:target="_blank"} choco 사용 gcc 설치 GCC (G++) 설치 패키지가 2개중에 하나 선택 mingw : https://community.chocolatey.org/packages/mingw{:target="_blank"} winlibs : https://community.chocolatey.org/packages/winlibs{:target="_blank"} winlibs가 버전이 높고 mingw는 버전인 올라가면서 posix thread가 문제가 있음 ...

2021년 8월 27일 · Byung Kyu KIM

Docker 내부 네트워크 상태 확인

netstat Host 머신에서 netstat 명령으로 docker container의 네트워크 상태가 확인 안됨 물론 container 내부에서 실행하면 되지만… docker container는 bridge 네트워크 기반으로 운영이 되므로 Host Network 에서는 노출이 안됨 # docker 실행 $ docker run -d -p 8081:80 --name=mvcapp cdecl/mvcapp 4fafaf418f84bf6541a1301b4422f825c58fa20b11d1190e87a3e23eea7a6825 # Host 에서는 publsh port (listen) 정보만 노출 $ netstat -ntl | grep 8081 tcp6 0 0 :::8081 :::* LISTEN # ip 현황 $ ip a ... 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000 link/ether 00:15:5d:3a:4a:00 brd ff:ff:ff:ff:ff:ff inet 192.168.137.100/24 brd 192.168.137.255 scope global noprefixroute eth0 valid_lft forever preferred_lft forever 4: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default <-- docker bridge link/ether 02:42:58:c6:1b:23 brd ff:ff:ff:ff:ff:ff inet 10.1.0.1/24 brd 10.1.0.255 scope global docker0 valid_lft forever preferred_lft forever ... # bridge network $ docker inspect -f '{{.NetworkSettings.Gateway}}' mvcapp 10.1.0.1 # 라우팅 정보 $ netstat -r Kernel IP routing table Destination Gateway Genmask Flags MSS Window irtt Iface default gateway 0.0.0.0 UG 0 0 0 eth0 10.1.0.0 0.0.0.0 255.255.255.0 U 0 0 0 docker0 <-- docker bridge 10.42.0.0 0.0.0.0 255.255.255.0 U 0 0 0 cni0 192.168.137.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0 nsenter https://github.com/jpetazzo/nsenter{:target="_blank"} 격리되어 있는 namespace enter 진입하는 명령 It is a small tool allowing to enter into namespaces. Technically, it can enter existing namespaces, or spawn a process into a new set of namespaces. ...

2021년 8월 26일 · Byung Kyu KIM

Golang, Cgo

Cgo enables the creation of Go packages that call C code. Cgo https://pkg.go.dev/cmd/cgo{:target="_blank"} Golang에서 C 코드를 통합 할 수 있도록 만든 의사 패키지 C코드 - Go 파일 통합 예제 import "C" 바로 윗 부분의 주석 /* */ or // 으로 C코드 작성 C 함수, 변수 영역 접근시, C 의 패키지 명으로 접근 함수, 변수선언, #include 선행처리지시자 등 일반적인 C 코드 cgo Cheat Sheet : https://gist.github.com/zchee/b9c99695463d8902cd33{:target="_blank"} package main /* #include <stdio.h> // printf #include <stdlib.h> // free (C.free) void println(const char *s) { printf("%s\n", s); } */ import "C" import ( "fmt" "unsafe" ) func main() { s := C.CString("c lang println") C.free(unsafe.Pointer(s)) C.println(s) fmt.Println("golang println") } $ go mod init main $ go build $ ./main c lang println golang println C코드 통합 - 별도 파일(C/C++)로 구성 같은 디렉토리의 C/C++ file extention 의 경우 기본 gcc(g++)로 빌드 및 링크 별도 파일의 경우 C++ 코드도 작성이 가능하나, golang 에서는 C언어 (Name mangling) 방식만 지원 Name mangling: 컴파일러가 함수명이나 변수이름을 특정한 규칙으로 변경 C++의 경우는 함수 Overloading으로 인해 C언어와 규칙이 다름 extern "C": C언어 방식의 Name mangling으로 처리 $ tree ├── go.mod ├── main.go └── print.cpp package main // #include <stdlib.h> // free // void println(char *s); import "C" import ( "fmt" "unsafe" ) func main() { s := C.CString("cpp println") C.free(unsafe.Pointer(s)) C.println(s) fmt.Println("golang println") } #include <iostream> using namespace std; extern "C" void println(const char *s); void println(const char *s) { cout << s << endl; } $ go build $ ./main cpp println Static, Dynamic library link $ tree ├── go.mod ├── main.go └── native ├── print.cpp └── print.h // print.h #pragma once #ifdef __cplusplus extern "C" { #endif void println(const char *s); #ifdef __cplusplus } #endif // print.cpp #include <iostream> #include "print.h" void println(const char *s) { std::cout << s << std::endl; } #cgo LDFLAG: 컴파일러 라이브러리 링크 옵션 지정 #cgo CFLAGS: 컴파일러 컴파일 옵션 package main // #cgo LDFLAGS: -Lnative -lprint -lstdc++ // #include <stdlib.h> // #include "native/print.h" import "C" import ( "fmt" "unsafe" ) func main() { s := C.CString("cpp println") C.free(unsafe.Pointer(s)) C.println(s) fmt.Println("golang println") } Static link $ cd native $ g++ -c print.cpp $ ar -cr libprint.a print.o $ cd .. $ go build $ ./main cpp println golang println Dynamic Link $ cd native $ g++ -dynamic -fPIC -o libprint.so -c libprint.cpp $ cd .. $ go build # Mac : export DYLD_LIBRARY_PATH=$(pwd)/native $ export LD_LIBRARY_PATH=/root/cgo/native $ ./main cpp println golang println 의존성 확인 Linux $ ldd ./main linux-vdso.so.1 (0x0000ffff9446a000) libprint.so => /root/cgo/native/libprint.so (0x0000ffff94428000) libpthread.so.0 => /lib/aarch64-linux-gnu/libpthread.so.0 (0x0000ffff943f7000) libc.so.6 => /lib/aarch64-linux-gnu/libc.so.6 (0x0000ffff94281000) libstdc++.so.6 => /usr/lib/aarch64-linux-gnu/libstdc++.so.6 (0x0000ffff940a9000) /lib/ld-linux-aarch64.so.1 (0x0000ffff9443a000) libm.so.6 => /lib/aarch64-linux-gnu/libm.so.6 (0x0000ffff93ffe000) libgcc_s.so.1 => /lib/aarch64-linux-gnu/libgcc_s.so.1 (0x0000ffff93fda000) Mac $ otool -L ./main ./main: libprint.so (compatibility version 0.0.0, current version 0.0.0) /usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 905.6.0) /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (compatibility version 150.0.0, current version 1775.118.101) /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1292.100.5) 예제 : char * 다루기 - string → *C.char : C.CString(string) // C.free(unsafe.Pointer(*C.char)) 메모리 해제 필수 - *C.char → string : C.GoString(*C.char) - []C.char' : byte slice → *C.char // buff := make([]byte, 128), (*C.char)(unsafe.Pointer(&buff[0])) - *C.char, C.int → string : C.GoStringN(*C.char, C.int) package main /* #include <stdlib.h> #include <string.h> */ import "C" import ( "fmt" "unsafe" ) func getptr(buff []byte) *C.char { return (*C.char)(unsafe.Pointer(&buff[0])) } func main() { buff := make([]byte, 128) s := C.CString("Hello") defer C.free(unsafe.Pointer(s)) C.strcpy(getptr(buff), s) fmt.Println(string(buff)) }

2021년 8월 23일 · Byung Kyu KIM

Docker Private Registry

Docker Private Registry 구성 Registry 실행 docker-compose.yml version: '3' services: registry: image: registry container_name: registry restart: always ports: - 5000:5000 environment: REGISTRY_HTTP_ADDR: 0.0.0.0:5000 volumes: - registry:/var/lib/registry - ./config.yml:/etc/docker/registry/config.yml volumes: registry: # 실행 $ docker-compose up -d $ curl -s http://localhost:5000/v2/_catalog {"repositories":[]} SSL 적용 version: '3' services: registry: image: registry container_name: private_registry restart: always ports: - 5000:5000 environment: REGISTRY_HTTP_ADDR: 0.0.0.0:5000 REGISTRY_HTTP_TLS_CERTIFICATE: /certs/domain-pem.pem REGISTRY_HTTP_TLS_KEY: /certs/domain-pem.key volumes: - registry:/var/lib/registry - ./config.yml:/etc/docker/registry/config.yml - ./certs:/certs volumes: registry: Image Push 테스트용 이미지 태깅 # get alpine images $ docker pull alpine $ docker pull alpine:3.13 # tagging $ docker tag alpine localhost:5000/cdecl/alpine:latest $ docker tag alpine:3.13 localhost:5000/cdecl/alpine:3.13 $ docker images REPOSITORY TAG IMAGE ID CREATED SIZE alpine latest ae607a46d002 2 weeks ago 5.33MB localhost:5000/cdecl/alpine latest ae607a46d002 2 weeks ago 5.33MB alpine 3.13 81efc9693413 2 months ago 5.35MB localhost:5000/cdecl/alpine 3.13 81efc9693413 2 months ago 5.35MB Image Push # image push $ docker push localhost:5000/cdecl/alpine:3.13 The push refers to repository [localhost:5000/cdecl/alpine] c55d5dbdab40: Layer already exists 3.13: digest: sha256:55fc95a51d97f7b76b124f3b581a58ebf5555d12574f16087de3971a12724dd4 size: 528 $ docker push localhost:5000/cdecl/alpine:latest The push refers to repository [localhost:5000/cdecl/alpine] 5bfa694cc00a: Layer already exists latest: digest: sha256:bd9137c3bb45dbc40cde0f0e19a8b9064c2bc485466221f5e95eb72b0d0cf82e size: 528 # Catalog list $ curl -s http://localhost:5000/v2/_catalog {"repositories":["cdecl/alpine"]} # Tag 정보 $ curl -s http://localhost:5000/v2/cdecl/alpine/tags/list {"name":"cdecl/alpine","tags":["latest","3.13"]} Image Pull $ docker pull localhost:5000/cdecl/alpine Using default tag: latest latest: Pulling from cdecl/alpine Digest: sha256:bd9137c3bb45dbc40cde0f0e19a8b9064c2bc485466221f5e95eb72b0d0cf82e Status: Downloaded newer image for localhost:5000/cdecl/alpine:latest localhost:5000/cdecl/alpine:latest Image Delete Tag 확인 -> Manifests 확인 -> Manifests 이미지 삭제 # Tag 정보 확인 $ curl -s http://localhost:5000/v2/cdecl/alpine/tags/list {"name":"cdecl/alpine","tags":["latest","3.13"]} # Tag의 Manifest 정보확인 - headers 확인 # <registry-url>/v2/<image-path-name>/manifests/<tag> $ curl -s -I -H "Accept: application/vnd.docker.distribution.manifest.v2+json" \ http://localhost:5000/v2/cdecl/alpine/manifests/latest HTTP/1.1 200 OK Content-Length: 528 Content-Type: application/vnd.docker.distribution.manifest.v2+json Docker-Content-Digest: sha256:bd9137c3bb45dbc40cde0f0e19a8b9064c2bc485466221f5e95eb72b0d0cf82e Docker-Distribution-Api-Version: registry/2.0 Etag: "sha256:bd9137c3bb45dbc40cde0f0e19a8b9064c2bc485466221f5e95eb72b0d0cf82e" # Manifest 정보로 이미지 삭제 # Docker-Content-Digest: <sha256:로 시작하는 해쉬 문자열> $ curl -s -XDELETE http://localhost:5000/v2/cdecl/alpine/manifests/sha256:bd9137c3bb45dbc40cde0f0e19a8b9064c2bc485466221f5e95eb72b0d0cf82e # 확인 $ curl -s http://localhost:5000/v2/cdecl/alpine/tags/list {"name":"cdecl/alpine","tags":["3.13"]} Delete marked manifests $ curl -sS http://localhost:5000/v2/cdecl/alpine/tags/list {"name":"cdecl/alpine","tags":null} $ docker exec -it registry bin/registry garbage-collect /etc/docker/registry/config.yml cdecl/alpine 0 blobs marked, 3 blobs and 0 manifests eligible for deletion blob eligible for deletion: sha256:81efc9693413c6292235ea2c29ea07c149701140b98df6c1998bb91d41acf802 INFO[0000] Deleting blob: /docker/registry/v2/blobs/sha256/81/81efc9693413c6292235ea2c29ea07c149701140b98df6c1998bb91d41acf802 go.version=go1.11.2 instance.id=d8bbbd10-232a-457a-9ceb-312b7317da5f service=registry blob eligible for deletion: sha256:55fc95a51d97f7b76b124f3b581a58ebf5555d12574f16087de3971a12724dd4 INFO[0000] Deleting blob: /docker/registry/v2/blobs/sha256/55/55fc95a51d97f7b76b124f3b581a58ebf5555d12574f16087de3971a12724dd4 go.version=go1.11.2 instance.id=d8bbbd10-232a-457a-9ceb-312b7317da5f service=registry blob eligible for deletion: sha256:595b0fe564bb9444ebfe78288079a01ee6d7f666544028d5e96ba610f909ee43 INFO[0000] Deleting blob: /docker/registry/v2/blobs/sha256/59/595b0fe564bb9444ebfe78288079a01ee6d7f666544028d5e96ba610f909ee43 go.version=go1.11.2 instance.id=d8bbbd10-232a-457a-9ceb-312b7317da5f service=registry 위 작업으로는 물리적인 데이터가 삭제 안됨 # 물리적인 파일 삭제 $ docker exec -it registry rm -rf /var/lib/registry/docker/registry/v2/repositories/cdecl Script registry-image-delete.sh #!/bin/bash URI="$1" NAME="$2" TAG="$3" if [[ -z "$URI" ]]; then echo "Usage: $0 <URI> <NAME> [<TAG>]" exit -1 fi if [[ -z "$NAME" ]]; then echo "Usage: $0 $URI <NAME> [<TAG>]" echo curl -sS $URI/v2/_catalog | jq -r '.repositories[]' echo exit -1 fi if [[ -z "$TAG" ]]; then echo "Usage: $0 $URI $NAME [<TAG>]" echo curl -sS $URI/v2/$NAME/tags/list | jq -r '.tags[]' echo exit -1 fi MANIFESTS=$(curl -sS -I -H "Accept: application/vnd.docker.distribution.manifest.v2+json" \ $URI/v2/$NAME/manifests/$TAG | grep -i Docker-Content-Digest | awk '{print $2}') if [[ -z "$MANIFESTS" ]]; then echo "No manifest found for $NAME:$TAG" exit -1 fi echo $MANIFESTS echo echo curl -sS -XDELETE $URI/v2/$NAME/manifests/$MANIFESTS echo

2021년 8월 22일 · Byung Kyu KIM

oh-my-zsh so slow (WSL)

oh-my-zsh 이 느린 경우 해결 방법 (특히 WSL) oh-my-zsh so slow Theme 가 느린 경우는 Pass git 관리 디렉토리 진입시 현저히 느려지는 경우 $ git config --global oh-my-zsh.hide-status 1 $ git config --global oh-my-zsh.hide-dirty 1 $ git config --global -l oh-my-zsh.hide-status=1 oh-my-zsh.hide-dirty=1

2021년 8월 22일 · Byung Kyu KIM

Mac Application

Mac 설치 어플리케이션 brew 패키지 관리자 https://brew.sh/index_ko{:target="_blank"} # 설치 $ brew search iterm2 $ brew install iterm2 karabiner-elements brew install brew search karabiner https://karabiner-elements.pqrs.org/{:target="_blank"} 오른쪽 command 버튼 한영키로 매핑 iTerm2 터미널 brew install iterm2 Zsh, Oh My Zsh https://github.com/ohmyzsh/ohmyzsh{:target="_blank"} # zsh install $ brew install zsh # oh my zsh VSCode https://code.visualstudio.com/{:target="_blank"} Docker https://www.docker.com/get-started{:target="_blank"} Dbeaver DB Tool brew install dbeaver-community IINA 동영상 플레이어 brew install iina https://iina.io/{:target="_blank"} Mounty NTFS Mount brew search mounty https://mounty.app/{:target="_blank"} Keka 압축프로그램 brew install keka https://www.keka.io/ko/{:target="_blank"}

2021년 8월 19일 · Byung Kyu KIM

Vim 최소 설정

vim 최소 설정 .vimrc set ts=4 set autoindent set cindent set hlsearch set showmatch if has("syntax") syntax on endif

2021년 8월 19일 · Byung Kyu KIM

Httplib (cpp-httplib) Sample

Introduction https://github.com/yhirose/cpp-httplib{:target="_blank"} A C++11 single-file header-only cross platform HTTP/HTTPS library. This is a multi-threaded ‘blocking’ HTTP library header-only 라이브러리로 Server와 Client Http 지원 SSL을 위한 OpenSSL 필요 cpprestsdk비해 가볍고, 쉽게 사용 가능 Httplib package install (w/ vcpkg) https://github.com/microsoft/vcpkg{:target="_blank"} vcpkg 통해서 패키지 설치 header-only로 바로 사용가능하나 OpenSSL 필요시 패키지 설치가 용이 # --triplet=x64-windows-static $ vcpkg.exe install cpp-httplib openssl --triplet=x64-windows-static ... The package cpp-httplib:x64-windows-static is header only and can be used from CMake via: find_path(CPP_HTTPLIB_INCLUDE_DIRS "httplib.h") target_include_directories(main PRIVATE ${CPP_HTTPLIB_INCLUDE_DIRS}) The package openssl is compatible with built-in CMake targets: find_package(OpenSSL REQUIRED) target_link_libraries(main PRIVATE OpenSSL::SSL OpenSSL::Crypto) Json test https://github.com/nlohmann/json{:target="_blank"} $ vcpkg.exe install nlohmann-json --triplet=x64-windows-static The package nlohmann-json:x64-windows-static provides CMake targets: find_package(nlohmann_json CONFIG REQUIRED) target_link_libraries(main PRIVATE nlohmann_json nlohmann_json::nlohmann_json) Sample code HTTPS 호출을 위해 CPPHTTPLIB_OPENSSL_SUPPORT 매크로가 정의 되어 있어야 함 정의하지 않고 HTTPS 호출시 : 'https' scheme is not supported. using namespace std; std namespace 노출시 byte 타입 정의 모호함으로 인한 에러 발생 표준 라이브러리 보다 먼저 선언되던가 using namespace std;를 피해야 함 ‘byte’: 모호한 기호입니다. #define CPPHTTPLIB_OPENSSL_SUPPORT #include <httplib.h> #include <iostream> using namespace std; #include <nlohmann/json.hpp> using json = nlohmann::json; void HttpRequest() { httplib::Client cli("https://httpbin.org"); { auto resp = cli.Get("/get"); cout << "status: " << resp->status << endl; cout << resp->body << endl; } { auto resp = cli.Post("/post"); cout << "status: " << resp->status << endl; cout << resp->body << endl; auto js = json::parse(resp->body); cout << "User-Agent: " << js["headers"]["User-Agent"] << endl; } } int main() { try { HttpRequest(); } catch (exception &e) { cerr << e.what() << endl; } catch (...) { cerr << "catch ..." << endl; } return 0; } CMakeLists.txt cmake_minimum_required(VERSION 3.11) project(main) set(CMAKE_CXX_STANDARD 17) add_executable(main main.cpp) target_compile_options(main PRIVATE /MT) find_package(OpenSSL REQUIRED) target_link_libraries(main PRIVATE OpenSSL::SSL OpenSSL::Crypto) find_path(CPP_HTTPLIB_INCLUDE_DIRS "httplib.h") target_include_directories(main PRIVATE ${CPP_HTTPLIB_INCLUDE_DIRS}) find_package(nlohmann_json CONFIG REQUIRED) target_link_libraries(main PRIVATE nlohmann_json nlohmann_json::nlohmann_json) $ mkdir build && cd build # x64-windows-static $ cmake -G "Visual Studio 16 2019" -A x64 .. -DCMAKE_TOOLCHAIN_FILE=D:/Lib/vcpkg/scripts/buildsystems/vcpkg.cmake -DVCPKG_TARGET_TRIPLET=x64-windows-static Build & Run # build $ echo cmake --build . --config Release > make.bat $ make.bat # run $ Release\main.exe status: 200 { "args": {}, "headers": { "Accept": "*/*", "Cache-Control": "max-stale=0", "Host": "httpbin.org", "User-Agent": "cpp-httplib/0.9", "X-Amzn-Trace-Id": "Root=1-611dba9f-0bdb46bb04c05b410da75cf4", "X-Bluecoat-Via": "ce2cfae06b3f12b4" }, "origin": "xx.xx.xx.xx", "url": "https://httpbin.org/get" } status: 200 { "args": {}, "data": "", "files": {}, "form": {}, "headers": { "Accept": "*/*", "Content-Length": "0", "Host": "httpbin.org", "User-Agent": "cpp-httplib/0.9", "X-Amzn-Trace-Id": "Root=1-611dba9f-091d99a41e5b3c023550162f", "X-Bluecoat-Via": "ce2cfae06b3f12b4" }, "json": null, "origin": "xx.xx.xx.xx", "url": "https://httpbin.org/post" } User-Agent: "cpp-httplib/0.9"

2021년 8월 18일 · Byung Kyu KIM