# Docker Spaces

Spaces menyediakan [kontainer Docker](https://docs.docker.com/get-started/) kustom untuk aplikasi di luar cakupan Streamlit dan Gradio. Docker Spaces memungkinkan pengguna melampaui batasan yang sebelumnya tidak mungkin dicapai dengan SDK standar. Dari endpoint FastAPI dan Go hingga aplikasi Phoenix dan alat ML Ops, Docker Spaces dapat membantu dalam berbagai konfigurasi.

## Mengatur Docker Spaces

Memilih **Docker** sebagai SDK saat [membuat Space baru](https://huggingface.co/new-space) akan menginisialisasi Space Anda dengan mengatur properti `sdk` menjadi `docker` di blok YAML pada file `README.md` Anda. Sebagai alternatif, untuk repositori Space yang sudah ada, atur `sdk: docker` di dalam blok `YAML` di bagian atas file **README.md** Spaces Anda. Anda juga dapat mengubah port yang diekspos secara default `7860` dengan mengatur `app_port: 7860`. Setelah itu, Anda dapat membuat `Dockerfile` biasa.

```Yaml
---
title: Basic Docker SDK Space
emoji: 🐳
colorFrom: purple
colorTo: gray
sdk: docker
app_port: 7860
---
```

Secara internal, Anda dapat memiliki sebanyak mungkin port terbuka yang Anda inginkan. Misalnya, Anda dapat menginstal Elasticsearch di dalam Space Anda dan memanggilnya secara internal pada port default 9200.

Jika Anda ingin mengekspos aplikasi yang disajikan di beberapa port ke dunia luar, solusi alternatifnya adalah menggunakan reverse proxy seperti Nginx untuk meneruskan permintaan dari internet yang lebih luas (pada satu port) ke port internal yang berbeda.

## Manajemen Secrets dan Variabel
 

Anda dapat mengelola variabel lingkungan sebuah Space di Pengaturan Space. Baca selengkapnya [di sini](./spaces-overview#managing-secrets).

### Variabel

#### Waktu build

Variabel dilewatkan sebagai `build-arg` saat membangun Docker Space Anda. Baca [dokumentasi khusus Docker](https://docs.docker.com/engine/reference/builder/#arg) untuk panduan lengkap tentang cara menggunakannya dalam Dockerfile.

```Dockerfile
	# Declare your environment variables with the ARG directive
	ARG MODEL_REPO_NAME

	FROM python:latest
	# [...]
	# You can use them like environment variables
	RUN predict.py $MODEL_REPO_NAME
```

#### Runtime

Variabel disuntikkan ke lingkungan kontainer pada saat runtime.

### Rahasia

#### Waktu build

Di Docker Spaces, manajemen rahasia berbeda karena alasan keamanan. Setelah Anda membuat rahasia di [tab Pengaturan](./spaces-overview#managing-secrets), Anda dapat mengekspos rahasia tersebut dengan menambahkan baris berikut di Dockerfile Anda:

Sebagai contoh, jika `SECRET_EXAMPLE` adalah nama secret yang Anda buat di tab Settings, Anda dapat membacanya saat build dengan cara memount-nya ke file, lalu membacanya dengan `$(cat /run/secrets/SECRET_EXAMPLE)`.

Lihat contoh di bawah ini:
```Dockerfile
# Expose the secret SECRET_EXAMPLE at buildtime and use its value as git remote URL
RUN --mount=type=secret,id=SECRET_EXAMPLE,mode=0444,required=true \
 git init && \
 git remote add origin $(cat /run/secrets/SECRET_EXAMPLE)
```

```Dockerfile
# Expose the secret SECRET_EXAMPLE at buildtime and use its value as a Bearer token for a curl request
RUN --mount=type=secret,id=SECRET_EXAMPLE,mode=0444,required=true \
	curl test -H 'Authorization: Bearer $(cat /run/secrets/SECRET_EXAMPLE)'
```

#### Runtime

Sama seperti untuk Variabel publik, pada saat runtime, Anda dapat mengakses rahasia sebagai variabel lingkungan. Misalnya, di Python Anda akan menggunakan `os.environ.get("SECRET_EXAMPLE")`. Lihat [contoh](https://huggingface.co/spaces/DockerTemplates/secret-example) ini tentang Docker Space yang menggunakan rahasia.

## Izin

Kontainer dijalankan dengan user ID 1000. Untuk menghindari masalah izin, Anda harus membuat user dan mengatur `WORKDIR` miliknya sebelum perintah `COPY` atau unduhan apa pun.

```Dockerfile
# Set up a new user named "user" with user ID 1000
RUN useradd -m -u 1000 user

# Switch to the "user" user
USER user

# Set home to the user's home directory
ENV HOME=/home/user \
	PATH=/home/user/.local/bin:$PATH

# Set the working directory to the user's home directory
WORKDIR $HOME/app

# Try and run pip command after setting the user with `USER user` to avoid permission issues with Python
RUN pip install --no-cache-dir --upgrade pip

# Copy the current directory contents into the container at $HOME/app setting the owner to the user
COPY --chown=user . $HOME/app

# Download a checkpoint
RUN mkdir content
ADD --chown=user https://<SOME_ASSET_URL> content/<SOME_ASSET_NAME>
```

Selalu tentukan `--chown=user` dengan `ADD` dan `COPY` untuk memastikan file baru dimiliki oleh pengguna Anda.

Jika Anda masih menghadapi masalah izin, Anda mungkin perlu menggunakan `chmod` atau `chown` di `Dockerfile` Anda untuk memberikan izin yang tepat. Misalnya, jika Anda ingin menggunakan direktori `/data`, Anda dapat melakukan:

```Dockerfile
RUN mkdir -p /data
RUN chmod 777 /data
```

Anda harus selalu menghindari chown yang tidak perlu.
> [!WARNING]
> Memperbarui metadata untuk sebuah file membuat salinan baru yang disimpan di layer baru. Oleh karena itu, chown rekursif dapat menghasilkan image yang sangat besar akibat duplikasi semua file yang terpengaruh.

Alih-alih memperbaiki izin dengan menjalankan `chown`:
```
COPY checkpoint .
RUN chown -R user checkpoint
```
Anda harus selalu melakukan:
```
COPY --chown=user checkpoint .
```
(hal yang sama berlaku untuk perintah `ADD`)

## Persistensi Data

Data yang ditulis ke disk akan hilang setiap kali Docker Space Anda dimulai ulang. Untuk mempertahankan data antar pemindaian ulang, Anda dapat melampirkan [Storage Bucket](./storage-buckets) ke Space Anda.

Saat ini, volume `/data` hanya tersedia saat runtime, yaitu Anda tidak dapat menggunakan `/data` selama langkah build dari Dockerfile Anda.

Anda juga dapat menggunakan Datasets Hub kami untuk kasus tertentu, di mana Anda dapat menyimpan state dan data dalam repositori git LFS. Anda dapat menemukan contoh persistensi [di sini](https://huggingface.co/spaces/Wauplin/space_to_dataset_saver), yang menggunakan [library `huggingface_hub`](https://huggingface.co/docs/huggingface_hub/index) untuk mengunggah file secara programatis ke repositori dataset. Contoh Space ini bersama dengan [panduan ini](https://huggingface.co/docs/huggingface_hub/main/en/guides/upload#scheduled-uploads) akan membantu Anda menentukan solusi mana yang paling sesuai dengan tipe data Anda.

Terakhir, dalam beberapa kasus, Anda mungkin ingin menggunakan solusi penyimpanan eksternal dari kode Space Anda, seperti DB yang di-hosting secara eksternal, S3, dan sebagainya.

### Kontainer Docker dengan GPU

Anda dapat menjalankan kontainer Docker dengan dukungan GPU menggunakan salah satu [Spaces Hardware](./spaces-gpus) berflavor GPU kami.

Kami merekomendasikan penggunaan [`nvidia/cuda`](https://hub.docker.com/r/nvidia/cuda) dari Docker Hub sebagai gambar dasar, yang sudah dilengkapi dengan CUDA dan cuDNN terpasang.

Selama proses build Docker, Anda tidak memiliki akses ke perangkat keras GPU. Oleh karena itu, Anda tidak boleh mencoba menjalankan perintah apa pun yang terkait dengan GPU selama langkah build pada Dockerfile Anda. Misalnya, Anda tidak dapat menjalankan `nvidia-smi` atau `torch.cuda.is_available()` saat membangun image. Baca selengkapnya [di sini](https://github.com/NVIDIA/nvidia-docker/wiki/nvidia-docker#description).

## Baca Selengkapnya

- [Contoh demo Docker lengkap](spaces-sdks-docker-first-demo)
- [Daftar contoh Docker Spaces](spaces-sdks-docker-examples)
- [Contoh Spaces](https://huggingface.co/SpacesExamples)

