Getting Started
Prerequisites
- EiffelStudio 25.02 or later
- Docker Desktop running on Windows
- Docker Engine accessible via named pipe (
\\.\pipe\docker_engine)
Installation
- Clone the repository:
git clone https://github.com/simple-eiffel/simple_docker.git - Set environment variables:
# Windows set SIMPLE_EIFFEL=D:\prod # MSYS2/Git Bash export SIMPLE_EIFFEL=/d/prod - Add to your ECF file:
<library name="simple_docker" location="$SIMPLE_EIFFEL/simple_docker/simple_docker.ecf"/>
Dependencies
Ensure these libraries are available:
simple_ipc- Named pipe communicationsimple_json- JSON parsingsimple_file- File operationssimple_logger- Logging
Beginner API (SIMPLE_DOCKER_QUICK)
New to Docker? The SIMPLE_DOCKER_QUICK class provides one-liner operations
that handle all the complexity for you. No Docker knowledge required!
Getting Started
local
docker: SIMPLE_DOCKER_QUICK
do
create docker.make
-- That's it! You're ready to use Docker.
end
Web Servers
-- Serve files from a folder on port 8080
docker.web_server ("C:\my_website", 8080)
-- Or explicitly choose Nginx or Apache
docker.web_server_nginx ("C:\my_website", 8080)
docker.web_server_apache ("C:\my_website", 8081)
Databases
-- PostgreSQL on default port 5432
docker.postgres ("mypassword")
-- PostgreSQL on custom port
docker.postgres_on_port ("mypassword", 5433)
-- MySQL on port 3306
docker.mysql ("mypassword")
-- MariaDB
docker.mariadb ("mypassword")
-- MongoDB (no auth)
docker.mongodb
Caches & Message Queues
-- Redis on port 6379
docker.redis
-- Redis on custom port
docker.redis_on_port (6380)
-- Memcached
docker.memcached
-- RabbitMQ (ports 5672 and 15672 for management UI)
docker.rabbitmq
Running Scripts
-- Run a shell script and get output
print (docker.run_script ("echo hello && date"))
-- Run Python code
print (docker.run_python ("print(2+2)"))
Cleanup
-- Stop all containers started by this facade
docker.stop_all
-- Stop AND remove all containers
docker.cleanup
Checking Status
-- Is Docker available?
if docker.is_available then
print ("Docker is running%N")
end
-- How many containers are we managing?
print ("Managing " + docker.container_count.out + " containers%N")
-- Did the last operation fail?
if docker.has_error then
print ("Error: " + docker.last_error_message + "%N")
end
Advanced Access
Need more control? Access the underlying DOCKER_CLIENT:
-- Get full control when needed
docker.client.list_containers (True).do_nothing
Full API: Connecting to Docker
Creating a Client
local
client: DOCKER_CLIENT
do
create client.make
-- Check connection
if client.ping then
print ("Docker daemon is responsive%N")
else
print ("Cannot connect to Docker%N")
end
end
Getting Version Information
if attached client.version as v then
print ("Docker Version: " + v.to_json + "%N")
end
if attached client.info as i then
print ("Docker Info: " + i.to_json + "%N")
end
Working with Containers
Creating a Container Specification
Use the fluent builder API to configure containers:
local
spec: CONTAINER_SPEC
do
create spec.make ("alpine:latest")
spec.set_name ("my-container")
.set_hostname ("myhost")
.set_cmd (<<"echo", "Hello!">>)
.add_env ("DEBUG", "true")
.add_env ("APP_NAME", "myapp").do_nothing
end
Port Mapping
spec.add_port (80, 8080) -- Map container:80 to host:8080
.add_port (443, 8443) -- Map container:443 to host:8443
.add_port_udp (53, 5353) -- UDP port mapping
.do_nothing
Volume Mounts
spec.add_volume ("/host/data", "/container/data")
.add_volume_readonly ("/host/config", "/etc/config")
.do_nothing
Resource Limits
spec.set_memory_limit (512 * 1024 * 1024) -- 512 MB
.set_cpu_shares (1024)
.do_nothing
Restart Policies
spec.set_restart_policy ("no") -- Never restart
spec.set_restart_policy ("always") -- Always restart
spec.set_restart_policy ("on-failure") -- Restart on failure
spec.set_restart_policy ("unless-stopped") -- Restart unless stopped
Running Containers
local
container: detachable DOCKER_CONTAINER
do
-- Create and start in one step
container := client.run_container (spec)
-- Or create then start separately
container := client.create_container (spec)
if attached container as c then
client.start_container (c.id).do_nothing
end
end
Container Lifecycle
-- Stop with timeout (seconds)
client.stop_container (container.id, 10).do_nothing
-- Pause/unpause
client.pause_container (container.id).do_nothing
client.unpause_container (container.id).do_nothing
-- Restart
client.restart_container (container.id, 10).do_nothing
-- Kill (force stop)
client.kill_container (container.id).do_nothing
-- Remove (force removes running containers)
client.remove_container (container.id, True).do_nothing
Getting Logs
if attached client.container_logs (container.id, True, True, 100) as logs then
-- True, True = stdout, stderr
-- 100 = last 100 lines
print (logs)
end
Waiting for Exit
local
exit_code: INTEGER
do
exit_code := client.wait_container (container.id)
print ("Container exited with code: " + exit_code.out + "%N")
end
Working with Images
Listing Images
across client.list_images as img loop
print (img.out + "%N")
-- Shows: short_id (tags) size_mb MB
end
Checking Image Existence
if client.image_exists ("alpine:latest") then
print ("Alpine image is available%N")
end
Pulling Images
if client.pull_image ("nginx:alpine") then
print ("Image pulled successfully%N")
else
print ("Failed to pull image%N")
end
Removing Images
-- Remove image (force=False means won't remove if in use)
client.remove_image ("old-image:v1", False).do_nothing
-- Force remove
client.remove_image ("old-image:v1", True).do_nothing
Error Handling
Checking for Errors
container := client.create_container (spec)
if client.has_error then
if attached client.last_error as err then
print ("Error: " + err.out + "%N")
end
end
Error Types
if attached client.last_error as err then
if err.is_connection_error then
-- Cannot connect to Docker daemon
elseif err.is_timeout_error then
-- Operation timed out
elseif err.is_not_found then
-- Container/image not found (404)
elseif err.is_conflict then
-- Name already in use (409)
elseif err.is_server_error then
-- Docker daemon error (5xx)
end
if err.is_retryable then
-- Connection/timeout errors can be retried
end
end
Common Error Recovery Patterns
-- Auto-pull missing images
container := client.create_container (spec)
if client.has_error and then
attached client.last_error as err and then
err.is_not_found then
if client.pull_image (spec.image) then
container := client.create_container (spec)
end
end
-- Handle name conflicts
if client.has_error and then
attached client.last_error as err and then
err.is_conflict then
-- Remove existing container and retry
client.remove_container (spec.name, True).do_nothing
container := client.create_container (spec)
end
Container State
Querying State
if container.is_running then
print ("Container is running%N")
elseif container.is_paused then
print ("Container is paused%N")
elseif container.is_exited then
print ("Container has exited%N")
print ("Exit code: " + container.exit_code.out + "%N")
elseif container.is_dead then
print ("Container is dead%N")
end
Checking Available Operations
if container.can_start then
client.start_container (container.id).do_nothing
end
if container.can_stop then
client.stop_container (container.id, 10).do_nothing
end
if container.has_exited_successfully then
print ("Container completed successfully%N")
end