This guide covers how to generate images with AUTOMATIC1111 Stable Diffusion WebUI running locally in Docker.
Prerequisite: Complete environment-setup.md and start the Stable Diffusion stack before following this guide.
- Start the stack
- Download a model
- WebUI walkthrough
- Text-to-image (txt2img)
- Image-to-image (img2img)
- REST API examples
- Python client examples
- Per-model guide and examples
- Prompt engineering guide
- Parameter reference
- Managing models
From the repository root:
# NVIDIA GPU
docker compose -f stable-diffusion/docker-compose.nvidia.yml up -d
# AMD GPU
docker compose -f stable-diffusion/docker-compose.amd.yml up -d
# CPU only (slow — minutes per image)
docker compose -f stable-diffusion/docker-compose.cpu.yml up -dThe first startup takes a few minutes while it downloads the base image layers. Open http://localhost:7860 to access the WebUI.
Models are stored in the sd_models Docker volume and persist across restarts.
- Open http://localhost:7860
- Go to the Civitai Helper or Model Downloader extension (if installed), or use the terminal method below.
# Open a shell inside the container
docker exec -it stable-diffusion-webui bash
# Navigate to the models folder
cd /app/stable-diffusion-webui/models/Stable-diffusion/
# Download SD 2.1 (requires Hugging Face login for some models)
wget -q "https://huggingface.co/stabilityai/stable-diffusion-2-1/resolve/main/v2-1_768-ema-pruned.safetensors"
# Exit the container shell
exitdocker cp ~/Downloads/my-model.safetensors \
stable-diffusion-webui:/app/stable-diffusion-webui/models/Stable-diffusion/After copying, click 🔄 Refresh next to the model dropdown in the WebUI.
| Model | File | Size |
|---|---|---|
| SD 2.1 | v2-1_768-ema-pruned.safetensors | 5.2 GB |
| SDXL base | sd_xl_base_1.0.safetensors | 6.9 GB |
| SDXL refiner | sd_xl_refiner_1.0.safetensors | 6.1 GB |
| FLUX.1 [schnell] | See Hugging Face | ~24 GB |
| FLUX.1 [dev] | See Hugging Face | ~24 GB (gated) |
| SD 3.5 Large | See Hugging Face | ~16 GB (gated) |
Gated models require a Hugging Face account and model access request. Log in with
huggingface-cli logininside the container and use the access token.
Open http://localhost:7860.
| Tab | Purpose |
|---|---|
| txt2img | Generate images from a text prompt |
| img2img | Transform or vary an existing image |
| Extras | Upscale, face restoration |
| PNG Info | Read generation parameters from a saved image |
| Settings | Configure defaults, extensions, and server options |
- Checkpoint (top-left) — select which model file to use; click 🔄 to refresh after adding new files
- Prompt — positive prompt (what to include)
- Negative prompt — what to exclude
- Sampling method — the diffusion algorithm (DPM++ 2M Karras is a reliable default)
- Sampling steps — more steps = higher quality but slower (20–30 is a good range)
- Width / Height — output image resolution
- CFG Scale — how closely to follow the prompt (7–12 is typical)
- Seed —
-1for random; fix a seed to reproduce an image exactly
- Select a model from the Checkpoint dropdown.
- Enter a positive prompt in the top text box.
- (Optional) Enter a negative prompt.
- Click Generate.
Landscape photography:
Prompt:
a misty mountain valley at sunrise, golden hour light, pine forest,
photorealistic, 8k, shot on Canon EOS R5, depth of field
Negative prompt:
cartoon, painting, blurry, low quality, watermark, text
Portrait:
Prompt:
portrait of a woman in her 30s, soft studio lighting, bokeh background,
professional headshot, high resolution, sharp focus
Negative prompt:
deformed, ugly, bad anatomy, extra limbs, watermark, signature
Concept art:
Prompt:
futuristic city at night, neon reflections on wet street, flying cars,
cyberpunk aesthetic, detailed, artstation, by Greg Rutkowski
Negative prompt:
blurry, low resolution, oversaturated, distorted
Img2img lets you start from an existing image and guide the generation with a prompt.
- Click the img2img tab.
- Upload a source image by dragging it into the canvas or clicking the upload icon.
- Enter a prompt describing what you want the output to look like.
- Adjust Denoising strength:
0.3–0.5— subtle variation, stays close to original0.6–0.8— significant change0.9–1.0— almost entirely new image
- Click Generate.
- Style transfer — change the art style while keeping composition
- Inpainting — fill in or replace part of an image (use the Inpaint sub-tab)
- Upscaling with detail — use img2img with low denoising at 2× resolution
- Sketch to image — turn a rough sketch into a rendered image
The WebUI exposes a REST API at http://localhost:7860/sdapi/v1/. The full Swagger UI is available at http://localhost:7860/docs.
curl -s -X POST http://localhost:7860/sdapi/v1/txt2img \
-H "Content-Type: application/json" \
-d '{
"prompt": "a cozy cabin in a snowy forest, warm light from windows, evening, photorealistic",
"negative_prompt": "blurry, low quality, cartoon, painting",
"steps": 25,
"cfg_scale": 7.5,
"width": 512,
"height": 512,
"sampler_name": "DPM++ 2M Karras",
"seed": -1
}' | python3 -c "
import sys, json, base64
data = json.load(sys.stdin)
img = base64.b64decode(data['images'][0])
open('output.png', 'wb').write(img)
print('Saved output.png')
"# Encode the source image to base64
BASE64_IMAGE=$(base64 -w 0 input.png)
curl -s -X POST http://localhost:7860/sdapi/v1/img2img \
-H "Content-Type: application/json" \
-d "{
\"init_images\": [\"${BASE64_IMAGE}\"],
\"prompt\": \"oil painting style, impressionist, vibrant colors\",
\"denoising_strength\": 0.65,
\"steps\": 20,
\"cfg_scale\": 7,
\"width\": 512,
\"height\": 512
}" | python3 -c "
import sys, json, base64
data = json.load(sys.stdin)
img = base64.b64decode(data['images'][0])
open('output_img2img.png', 'wb').write(img)
print('Saved output_img2img.png')
"curl http://localhost:7860/sdapi/v1/sd-models | python3 -m json.toolcurl -X POST http://localhost:7860/sdapi/v1/options \
-H "Content-Type: application/json" \
-d '{"sd_model_checkpoint": "v2-1_768-ema-pruned.safetensors"}'curl http://localhost:7860/sdapi/v1/options | python3 -m json.toolpip install requests pillowimport requests
import base64
from PIL import Image
from io import BytesIO
def txt2img(prompt: str, negative_prompt: str = "", steps: int = 25, **kwargs) -> Image.Image:
payload = {
"prompt": prompt,
"negative_prompt": negative_prompt,
"steps": steps,
"cfg_scale": kwargs.get("cfg_scale", 7.5),
"width": kwargs.get("width", 512),
"height": kwargs.get("height", 512),
"sampler_name": kwargs.get("sampler_name", "DPM++ 2M Karras"),
"seed": kwargs.get("seed", -1),
}
response = requests.post("http://localhost:7860/sdapi/v1/txt2img", json=payload)
response.raise_for_status()
image_data = base64.b64decode(response.json()["images"][0])
return Image.open(BytesIO(image_data))
# Generate an image
image = txt2img(
prompt="a serene Japanese garden with a koi pond, cherry blossoms, golden hour",
negative_prompt="people, text, watermark, low quality",
steps=30,
cfg_scale=8,
width=768,
height=512,
)
image.save("japanese_garden.png")
print("Saved japanese_garden.png")import requests, base64
from PIL import Image
from io import BytesIO
prompts = [
"a red apple on a wooden table, photorealistic",
"a blue sports car on a mountain road, cinematic",
"an abstract painting with swirling galaxies, vibrant colors",
]
for i, prompt in enumerate(prompts):
response = requests.post(
"http://localhost:7860/sdapi/v1/txt2img",
json={"prompt": prompt, "steps": 20, "width": 512, "height": 512},
)
image_data = base64.b64decode(response.json()["images"][0])
image = Image.open(BytesIO(image_data))
image.save(f"batch_{i}.png")
print(f"Saved batch_{i}.png")SD 2.1 uses a 768×768 native resolution. Best for general photography, landscapes, and portraits with simple prompts.
Recommended settings:
- Sampler:
DPM++ 2M Karras - Steps: 20–30
- CFG Scale: 7–9
- Resolution: 768×768
Example:
Prompt:
majestic eagle soaring above snow-capped mountains, dramatic clouds,
golden sunlight, wildlife photography, Canon EF 500mm, sharp focus
Negative prompt:
blurry, overexposed, low detail, cartoonish
SDXL produces 1024×1024 outputs and can be chained with the refiner model for enhanced detail.
Recommended settings:
- Sampler:
DPM++ 2M Karras - Steps: 30–40
- CFG Scale: 6–8
- Resolution: 1024×1024
Switch to SDXL:
curl -X POST http://localhost:7860/sdapi/v1/options \
-H "Content-Type: application/json" \
-d '{"sd_model_checkpoint": "sd_xl_base_1.0.safetensors"}'Example:
Prompt:
hyperrealistic portrait of an elderly sailor with weathered skin,
piercing blue eyes, white beard, dramatic ocean background,
studio lighting, 8k, photorealistic, Rembrandt lighting
Negative prompt:
cartoon, painting, unrealistic, bad anatomy, extra fingers, watermark
Using base + refiner (two-pass):
import requests, base64
from PIL import Image
from io import BytesIO
# Pass 1: base model generates a latent
base_response = requests.post("http://localhost:7860/sdapi/v1/txt2img", json={
"prompt": "a futuristic cityscape at dusk, neon lights reflecting on glass towers",
"steps": 40,
"cfg_scale": 7,
"width": 1024,
"height": 1024,
"denoising_strength": 0.8,
}).json()
# Save base output
base_image_bytes = base64.b64decode(base_response["images"][0])
Image.open(BytesIO(base_image_bytes)).save("sdxl_base.png")
# Pass 2: refiner polishes the output
requests.post("http://localhost:7860/sdapi/v1/options", json={
"sd_model_checkpoint": "sd_xl_refiner_1.0.safetensors"
})
refiner_response = requests.post("http://localhost:7860/sdapi/v1/img2img", json={
"init_images": [base_response["images"][0]],
"prompt": "a futuristic cityscape at dusk, neon lights reflecting on glass towers",
"denoising_strength": 0.3,
"steps": 20,
"cfg_scale": 7,
"width": 1024,
"height": 1024,
}).json()
Image.open(BytesIO(base64.b64decode(refiner_response["images"][0]))).save("sdxl_refined.png")
print("Saved sdxl_base.png and sdxl_refined.png")SD 3.5 is Stability AI's most recent release. It features significantly improved text rendering, prompt adherence, and composition. It requires at least 10 GB VRAM for the full model.
Recommended settings:
- Sampler:
Euler - Steps: 28
- CFG Scale: 4.5
- Resolution: 1024×1024
SD 3.5 uses a different architecture (MMDiT). Ensure the WebUI version supports it, or use a dedicated SD 3.5-compatible loader.
Example:
Prompt:
A glass bottle containing a tiny universe with swirling galaxies inside,
placed on an ancient wooden table, dramatic lighting, hyperrealistic macro photography
Negative prompt:
(none needed — SD 3.5 follows positive prompts very well)
FLUX.1 by Black Forest Labs achieves state-of-the-art image quality. It requires 16–24 GB VRAM for full performance. The schnell variant is faster; dev is higher quality.
Recommended settings:
- Sampler:
Euler - Steps: 4 (schnell) / 20–28 (dev)
- CFG Scale: 1 (schnell) / 3.5 (dev)
- Resolution: 1024×1024
FLUX.1 requires the
sd-forgeorComfyUIfrontend for best compatibility. AUTOMATIC1111 may require an extension.
Example:
Prompt (FLUX.1 schnell — 4 steps):
a photorealistic image of a golden retriever puppy playing in autumn leaves,
shallow depth of field, warm afternoon light
Negative prompt:
(FLUX.1 does not use negative prompts — leave empty)
# FLUX.1 schnell — fast generation (4 steps)
curl -s -X POST http://localhost:7860/sdapi/v1/txt2img \
-H "Content-Type: application/json" \
-d '{
"prompt": "a photorealistic image of a golden retriever puppy playing in autumn leaves, shallow depth of field",
"steps": 4,
"cfg_scale": 1,
"width": 1024,
"height": 1024,
"sampler_name": "Euler"
}' | python3 -c "
import sys, json, base64
data = json.load(sys.stdin)
open('flux_output.png', 'wb').write(base64.b64decode(data['images'][0]))
print('Saved flux_output.png')
"A well-structured prompt typically follows this pattern:
[subject], [setting/context], [style descriptors], [lighting], [camera/technical details], [quality boosters]
Example:
a lone wolf standing on a cliff, overlooking a misty valley,
oil painting style, dramatic, chiaroscuro lighting,
highly detailed, masterpiece, artstation
photorealistic, hyperrealistic, 8k, ultra-detailed, sharp focus,
masterpiece, best quality, professional, award-winning photography
blurry, low quality, low resolution, bad anatomy, deformed hands,
extra fingers, watermark, signature, text, username, artist name,
ugly, pixelated, overexposed, underexposed, grainy, noisy
Increase or decrease the influence of specific terms using parentheses:
# Increase weight (default multiplier: 1.1 per level)
(bright sunlight:1.4) a forest path
# Decrease weight
a forest path [rain:0.5]
When generating people, a detailed negative prompt helps:
bad anatomy, bad hands, extra fingers, missing fingers, fused fingers,
too many fingers, deformed, mutated, disfigured, poorly drawn face,
poorly drawn hands, extra limbs, missing limbs, floating limbs,
disconnected limbs, malformed limbs, ugly, duplicate, morbid
| Parameter | Typical range | Notes |
|---|---|---|
| Steps | 20–40 | More steps = better quality, slower. Diminishing returns above 40 |
| CFG Scale | 5–12 | How strictly to follow the prompt. Higher = more literal but may lose realism |
| Denoising strength | 0.3–0.9 | img2img only. Lower = more similar to input image |
| Width / Height | 512–1024 | Stay near the model's native resolution. SDXL/FLUX: 1024. SD 2.1: 768 |
| Seed | -1 or any int | -1 = random. Fix seed to reproduce images exactly |
| Batch size | 1–4 | Number of images per generation (uses more VRAM) |
| Batch count | 1–8 | Number of sequential generation runs |
| Sampler | Speed | Quality | Notes |
|---|---|---|---|
| Euler | Fast | Good | Reliable default, works well with FLUX |
| Euler a | Fast | Good | More variation per seed |
| DPM++ 2M Karras | Medium | Very good | Best general-purpose sampler for SD 1.x/2.x |
| DPM++ SDE Karras | Slow | Excellent | Highest detail, less predictable |
| DDIM | Medium | Good | Deterministic, useful for img2img |
| LMS Karras | Fast | Good | Fast convergence |
curl http://localhost:7860/sdapi/v1/sd-models | python3 -c "
import sys, json
for m in json.load(sys.stdin):
print(m['model_name'])
"curl http://localhost:7860/sdapi/v1/options | python3 -c "
import sys, json
opts = json.load(sys.stdin)
print('Current model:', opts.get('sd_model_checkpoint'))
"curl -X POST http://localhost:7860/sdapi/v1/options \
-H "Content-Type: application/json" \
-d '{"sd_model_checkpoint": "sd_xl_base_1.0.safetensors"}'# Enter the container and delete the file
docker exec -it stable-diffusion-webui \
rm /app/stable-diffusion-webui/models/Stable-diffusion/old-model.safetensorsdocker system df -v | grep sd_models