# Crear una compilación multi-etapa para tu aplicación C++


## Requisitos previos

- Tienes un [cliente git](https://git-scm.com/downloads). Los ejemplos de esta sección usan git por línea de comandos, pero puedes usar cualquier cliente.

## Descripción general

Esta sección te guía para crear una compilación Docker multi-etapa para una aplicación C++.
Una compilación multi-etapa es una función de Docker que te permite usar distintas imágenes base en distintas etapas del proceso de compilación,
de modo que puedes optimizar el tamaño de la imagen final y separar las dependencias de compilación de las de ejecución.

La práctica habitual en lenguajes compilados como C++ es tener una etapa de compilación que compila el código y una etapa de ejecución que ejecuta el binario compilado,
porque las dependencias de compilación no se necesitan en tiempo de ejecución.

## Obtener la aplicación de ejemplo

Usemos una aplicación C++ sencilla que imprime `Hello, World!` en la terminal. Para ello, clona el repositorio de ejemplo de esta guía:

```bash
$ git clone https://github.com/dockersamples/c-plus-plus-docker.git
```

El ejemplo de esta sección está en el directorio `hello` del repositorio. Entra y revisa los archivos:

```bash
$ cd c-plus-plus-docker/hello
$ ls
```

Deberías ver los siguientes archivos:

```text
Dockerfile  hello.cpp
```

## Revisar el Dockerfile

Abre el `Dockerfile` en un IDE o editor de texto. El `Dockerfile` contiene las instrucciones para compilar la imagen Docker.

```Dockerfile
# Stage 1: Build stage
FROM ubuntu:latest AS build

# Install build-essential for compiling C++ code
RUN apt-get update && apt-get install -y build-essential

# Set the working directory
WORKDIR /app

# Copy the source code into the container
COPY hello.cpp .

# Compile the C++ code statically to ensure it doesn't depend on runtime libraries
RUN g++ -o hello hello.cpp -static

# Stage 2: Runtime stage
FROM scratch

# Copy the static binary from the build stage
COPY --from=build /app/hello /hello

# Command to run the binary
CMD ["/hello"]
```

El `Dockerfile` tiene dos etapas:

1. **Etapa de compilación**: Usa la imagen `ubuntu:latest` para compilar el código C++ y crear un binario estático.
2. **Etapa de ejecución**: Usa la imagen `scratch`, que está vacía, para copiar el binario estático de la etapa de compilación y ejecutarlo.

## Compilar la imagen Docker

Para compilar la imagen Docker, ejecuta el siguiente comando en el directorio `hello`:

```bash
$ docker build -t hello .
```

La opción `-t` etiqueta la imagen con el nombre `hello`.

## Ejecutar el contenedor Docker

Para ejecutar el contenedor Docker, usa el siguiente comando:

```bash
$ docker run hello
```

Deberías ver la salida `Hello, World!` en la terminal.

## Resumen

En esta sección aprendiste a crear una compilación multi-etapa para una aplicación C++. Las compilaciones multi-etapa ayudan a optimizar el tamaño de la imagen final y a separar las dependencias de compilación de las de ejecución.
En este ejemplo, la imagen final solo contiene el binario estático y no incluye dependencias de compilación.

Como la imagen tiene una base vacía, tampoco están las herramientas habituales del SO. Por ejemplo, no puedes ejecutar un simple comando `ls` en el contenedor:

```bash
$ docker run hello ls
```

Eso hace la imagen muy ligera y segura.

