關於docker的scratch鏡像與helloworld
參考:https://hub.docker.com/_/scratch?tab=descriptionhtml
參考:https://segmentfault.com/a/1190000000628247linux
FROM scratchgit
官方說明:該鏡像是一個空的鏡像,能夠用於構建busybox等超小鏡像,能夠說是真正的從零開始構建屬於本身的鏡像。要知道,一個官方的ubuntu鏡像有60MB+,CentOS鏡像有70MB+github
能夠把一個可執行文件扔進來直接執行golang
1、注意:scratch不可用被pull
FROM scratch專門用於構建最小鏡像,直接pull會報如下錯誤,scratch是一個保留名稱docker
[root@es-master1 ~]# docker pull scratch Using default tag: latest Error response from daemon: 'scratch' is a reserved name
2、如何製做大小爲0 的鏡像
既然scratch不能被拉取,如何作到docker image ls
看到一個0字節的鏡像ubuntu
官方給出了下面方法:segmentfault
$ tar cv --files-from /dev/null | docker import - scratch $ docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE scratch latest 775bfce21429 9 minutes ago 0B
3、如何跑一個helloworld
能夠參考:https://github.com/docker-library/hello-world/bash
3.1C語言不行,docker是go語言寫的,跑的話報錯
[root@es-master1 ~]# cat hello.c #include <stdio.h> main() { printf("hello world\n"); }
[root@es-master1 ~]# gcc hello.c -o hello [root@es-master1 ~]# ll hello -rwxr-xr-x 1 root root 8440 Nov 21 03:36 hello
Dockerfileapp
FROM scratch COPY hello / CMD ["/hello"]
[root@es-master1 ~]# docker build -t hello . [root@es-master1 ~]# docker image ls hello REPOSITORY TAG IMAGE ID CREATED SIZE hello latest 3b89b5056a03 5 minutes ago 8.44kB
果真報錯
[root@es-master1 ~]# docker run --rm hello standard_init_linux.go:211: exec user process caused "no such file or directory"
ubuntu固然能夠
[root@es-master1 ~]# cat Dockerfile FROM ubuntu COPY hello / CMD ["/hello"] [root@es-master1 ~]# docker build -t hello . Sending build context to Docker daemon 24.63MB Step 1/3 : FROM ubuntu ---> 775349758637 Step 2/3 : COPY hello / ---> 33de2082f11a Step 3/3 : CMD ["/hello"] ---> Running in 3d347f62b926 Removing intermediate container 3d347f62b926 ---> 1829a7bd40fe Successfully built 1829a7bd40fe Successfully tagged hello:latest [root@es-master1 ~]# docker run --rm hello hello world
官方的這個居然有點看不懂了,c語言:https://github.com/docker-library/hello-world
[root@es-master1 tmp]# git clone https://github.com/docker-library/hello-world.git [root@es-master1 tmp]# cd hello-world/ [root@es-master1 hello-world]# make all [root@es-master1 hello-world]# amd64/hello-world/hello Hello from Docker! ......
3.2go語言
使用go語言寫:https://github.com/adriaandejonge/helloworld
[root@es-master1 hello-world]# tree -C . . ├── Dockerfile └── hello.go 0 directories, 2 files
[root@es-master1 hello-world]# cat hello.go package main import "fmt" func main(){ fmt.Printf("hello world\n") }
[root@es-master1 hello-world]# cat Dockerfile FROM google/golang as builder WORKDIR /go/src/app COPY hello.go . RUN go build hello.go FROM scratch COPY --from=builder /go/src/app/hello / CMD ["/hello"]
一個helloworld都這麼大...
[root@es-master1 hello-world]# docker build -t hello . [root@es-master1 hello-world]# docker image ls hello REPOSITORY TAG IMAGE ID CREATED SIZE hello latest 27eca431407a 2 minutes ago 2.36MB [root@es-master1 hello-world]# docker run --rm hello hello world
[root@es-master1 hello-world]# docker image history hello IMAGE CREATED CREATED BY SIZE COMMENT 27eca431407a 3 minutes ago /bin/sh -c #(nop) CMD ["/hello"] 0B 1a35249e8575 3 minutes ago /bin/sh -c #(nop) COPY file:7b1994197d7b5310… 2.36MB
也沒用過go,網上了解到加個選項就能變小:https://www.jianshu.com/p/1405b0c2c5a3
[root@es-master1 hello-world]# cat Dockerfile FROM google/golang as builder WORKDIR /go/src/app COPY hello.go . RUN go build -ldflags="-w -s" hello.go FROM scratch COPY --from=builder /go/src/app/hello / CMD ["/hello"] [root@es-master1 hello-world]# docker build -t hello . [root@es-master1 hello-world]# docker image ls hello REPOSITORY TAG IMAGE ID CREATED SIZE hello latest df8b3c8897f9 8 seconds ago 1.65MB
3.3改寫官方的helloword
hello.c
[root@es-master1 ~]# cat hello.c //#include <unistd.h> #include <sys/syscall.h> #ifndef DOCKER_GREETING #define DOCKER_GREETING "Hello from Docker!" #endif const char message[] = DOCKER_GREETING "\n"; void _start() { //write(1, message, sizeof(message) - 1); syscall(SYS_write, 1, message, sizeof(message) - 1); //_exit(0); syscall(SYS_exit, 0); }
編譯
[root@es-master1 ~]# gcc -static -Os -nostartfiles -fno-asynchronous-unwind-tables -o './hello' 'hello.c' [root@es-master1 ~]# strip -R .comment -s 'hello' [root@es-master1 ~]# ./hello Hello from Docker!
dockerfile
FROM scratch COPY hello / CMD ["/hello"]
[root@es-master1 ~]# docker build -t hello . #才1.06kB [root@es-master1 ~]# docker image ls hello REPOSITORY TAG IMAGE ID CREATED SIZE hello latest 3b204a40c8cb 14 seconds ago 1.06kB [root@es-master1 ~]# docker run --rm hello Hello from Docker!
4、補充
- gcc -D能夠定義宏,起到替換、條件編譯的功能;即hello.c中定義了一個宏,我能夠在gcc編譯時使用-D替換該宏。就好像我docker鏡像定義了一些變量,可是docker run仍能夠-e傳遞變量,覆蓋原有的變量
- gcc -static指定強制使用靜態庫,
- -O 對程序進行優化編譯、連接。採用這個選項,整個源代碼會在編譯、連接過程當中進行優化處理,這樣產生的可執行文件的執行效率能夠提升,可是編譯、連接的速度就相應地要慢一些,並且對執行文件的調試會產生必定的影響,形成一些執行效果與對應源文件代碼不一致等一些使人「困惑」的狀況。所以,通常在編譯輸出軟件發行版時使用此選項。
- -Os 使用了全部-O2的優化選項,但又不縮減代碼尺寸的方法 https://www.cnblogs.com/luolizhi/p/5737091.html
- -nostartfiles 鏈接的使用不使用標準系統庫。只有你指定的庫纔可以傳遞給鏈接器。不連接系統標準啓動文件,而標準庫文件仍然正常使用
- -fno-asynchronous-unwind-tables 用來不生成CFI指令
- -o 輸出文件名
- stribe 給文件脫褲子。具體就是從特定文件中剝掉一些符號信息和調試信息。 在strip以後, 文件變小了, 仍然能夠執行, 這就就節省了不少空間。