今天我們想要製造一個Docker容器來幫忙計算第N個斐波那契数,並決定用C++來撰寫執行程式。
下面是一個時間複雜度O(N)的計算程式:
fib.cpp
#include <iostream>
#include <exception>
using namespace std;
int fib(int n)
{
int f[] = {1, 0};
while (n)
{
auto temp = f[1];
f[1] = f[0] + f[1];
f[0] = temp;
--n;
}
return f[1];
}
int main(int argc, char *argv[])
{
if (argc < 2)
{
cerr << "Please give a positive number.(<=40)" << endl;
return 1;
}
int num;
try
{
num = stoi(argv[1]);
}
catch (...)
{
cerr << "Please give a positive number.(<=40)" << endl;
return 0;
}
if (num <= 0 || num > 40)
{
cerr << "Please give a positive number.(<=40)" << endl;
return 1;
}
cout << "The number " << num << " of fibonacci sequence is " << fib(num) << "." << endl;
return 0;
}
最直接的方式是用gcc image來幫助我們完成所要的容器:
Dockerfile
FROM gcc
COPY fib.cpp fib.cpp
RUN g++ fib.cpp -o fib
ENTRYPOINT ["/fib"]build 及 run 的結果:
$ docker build -t fib .
$ docker run --rm fib 10
The number 10 of fibonacci sequence is 55.這是一個簡單的計算程式,然而這樣的image卻佔有1gb以上,如果要分享這個image給其他人,實在太大了。
仔細思考,我們其實只要最終編譯的二進制執行檔,gcc image裡的編譯程式等都不需要。所以換個方式,先用gcc image編譯,再把編譯好的二進制檔案放到幾乎甚麼都沒有的scratch image裡面。
我們可以利用Docker提供的multi-stage build方式來完成:
Dockerfile
FROM gcc AS builder
COPY fib.cpp fib.cpp
RUN g++ -static fib.cpp -o fib
FROM scratch
COPY --from=builder fib /
ENTRYPOINT ["/fib"]記得g++後頭要加-static來避免執行時的dynamic linking,因為scratch image裡無法提供所需的東西。
最後,build後我們可以得到約2.4MB的image,比先前的小非常多!
