diff --git a/services/webapp/code/rosetta/core_app/admin.py b/services/webapp/code/rosetta/core_app/admin.py
index b69c3b232dc099e5e241bd162bf974503d6dd1eb..819a338386178021c1b0e3e17075f93740d63d28 100644
--- a/services/webapp/code/rosetta/core_app/admin.py
+++ b/services/webapp/code/rosetta/core_app/admin.py
@@ -2,10 +2,14 @@ from django.contrib import admin
 
 from .models import Profile, LoginToken, Task, Container, Computing, Storage, KeyPair, Page
 
+# Define a extra "ModelAdmin" for the Container model to allow "save as" to easily duplicate containers
+class ContainerForAdmin(admin.ModelAdmin):
+    save_as = True
+
 admin.site.register(Profile)
 admin.site.register(LoginToken)
 admin.site.register(Task)
-admin.site.register(Container)
+admin.site.register(Container, ContainerForAdmin)
 admin.site.register(Computing)
 admin.site.register(Storage)
 admin.site.register(KeyPair)
diff --git a/services/webapp/code/rosetta/core_app/computing_managers.py b/services/webapp/code/rosetta/core_app/computing_managers.py
index 6fe2a40ff6fc53eba3dfaf8c8137617c970f379c..e130bb85c3c9ae2d1b1b72390fde8ee39a87836f 100644
--- a/services/webapp/code/rosetta/core_app/computing_managers.py
+++ b/services/webapp/code/rosetta/core_app/computing_managers.py
@@ -111,7 +111,7 @@ class InternalSingleNodeComputingManager(SingleNodeComputingManager):
         #run_command += ' -v {}/user-{}:/data'.format(settings.LOCAL_USER_DATA_DIR, task.user.id)
 
         # Host name, image entry command
-        run_command += ' -h task-{} -d -t {}/{}:{}'.format(task.uuid, task.container.registry, task.container.image, task.container.tag)
+        run_command += ' -h task-{} -d -t {}/{}:{}'.format(task.uuid, task.container.registry, task.container.image_name, task.container.image_tag)
 
         # Debug
         logger.debug('Running new task with command="{}"'.format(run_command))
@@ -238,7 +238,7 @@ class SSHSingleNodeComputingManager(SingleNodeComputingManager, SSHComputingMana
             run_command += 'exec nohup singularity run {} --pid --writable-tmpfs --no-home --home=/home/metauser --workdir /tmp/{}_data/tmp -B/tmp/{}_data/home:/home --containall --cleanenv '.format(binds, task.uuid, task.uuid)
             
             # Container part
-            run_command+='docker://{}/{}:{} &>> /tmp/{}_data/task.log & echo \$!"\''.format(task.container.registry, task.container.image, task.container.tag, task.uuid)
+            run_command+='docker://{}/{}:{} &>> /tmp/{}_data/task.log & echo \$!"\''.format(task.container.registry, task.container.image_name, task.container.image_tag, task.uuid)
             
 
         else:
@@ -377,7 +377,7 @@ class SlurmSSHClusterComputingManager(ClusterComputingManager, SSHComputingManag
             run_command += 'exec nohup singularity run {} --pid --writable-tmpfs --no-home --home=/home/metauser --workdir /tmp/{}_data/tmp -B/tmp/{}_data/home:/home --containall --cleanenv '.format(binds, task.uuid, task.uuid)
             
             # Double to escape for Python, six for shell (double times three as \\\ escapes a single slash in shell)
-            run_command+='docker://{}/{}:{} &> \$HOME/{}.log\\" > \$HOME/{}.sh && sbatch {} \$HOME/{}.sh"\''.format(task.container.registry, task.container.image, task.container.tag, task.uuid, task.uuid, sbatch_args, task.uuid)
+            run_command+='docker://{}/{}:{} &> \$HOME/{}.log\\" > \$HOME/{}.sh && sbatch {} \$HOME/{}.sh"\''.format(task.container.registry, task.container.image_name, task.container.image_tag, task.uuid, task.uuid, sbatch_args, task.uuid)
 
         else:
             raise NotImplementedError('Default container runtime "{}" not supported'.format(task.computing.default_container_runtime))
diff --git a/services/webapp/code/rosetta/core_app/management/commands/core_app_populate.py b/services/webapp/code/rosetta/core_app/management/commands/core_app_populate.py
index b5ffae06cc56e4441f6b905413c9a933ed8b7b41..b3ac3be5cd48406153cfe001228d9e9be818a0fb 100644
--- a/services/webapp/code/rosetta/core_app/management/commands/core_app_populate.py
+++ b/services/webapp/code/rosetta/core_app/management/commands/core_app_populate.py
@@ -129,15 +129,15 @@ to provide help, news and informations on your deployment. Or you can just ignor
             
             # Minimal Desktop
             Container.objects.create(user     = None,
-                                     name     = 'Minimal Desktop ',
+                                     name     = 'Minimal Desktop',
                                      description = 'A minimal desktop environment providing basic window management functionalities and a terminal.',
                                      registry = 'docker.io',
-                                     image    = 'sarusso/minimaldesktop',
-                                     tag      = 'v0.2.0',
-                                     arch = 'x86_64',
-                                     os = 'linux',
-                                     interface_port     = '8590',
-                                     interface_protocol = 'http',
+                                     image_name = 'sarusso/minimaldesktop',
+                                     image_tag  = 'v0.2.0',
+                                     image_arch = 'amd64',
+                                     image_os   = 'linux',
+                                     interface_port      = '8590',
+                                     interface_protocol  = 'http',
                                      interface_transport = 'tcp/ip',
                                      supports_custom_interface_port = True,
                                      supports_interface_auth = True)
@@ -147,43 +147,76 @@ to provide help, news and informations on your deployment. Or you can just ignor
                                      name     = 'Basic Desktop',
                                      description = 'A basic desktop environment. Provides a terminal, a file manager, a web browser and other generic applications.',
                                      registry = 'docker.io',
-                                     image    = 'sarusso/basicdesktop',
-                                     tag      = 'v0.2.0',
-                                     arch = 'x86_64',
-                                     os = 'linux',
-                                     interface_port     = '8590',
-                                     interface_protocol = 'http',
+                                     image_name = 'sarusso/basicdesktop',
+                                     image_tag  = 'v0.2.0',
+                                     image_arch = 'amd64',
+                                     image_os   = 'linux',
+                                     interface_port      = '8590',
+                                     interface_protocol  = 'http',
                                      interface_transport = 'tcp/ip',
                                      supports_custom_interface_port = True,
                                      supports_interface_auth = True,
                                      interface_auth_user = None)
  
  
-            # Jupyter Notebook 
+            # Jupyter Notebook
             Container.objects.create(user     = None,
                                      name     = 'Jupyter Notebook',
                                      description = 'A Jupyter Notebook server',
                                      registry = 'docker.io',
-                                     image    = 'sarusso/jupyternotebook',
-                                     tag      = 'v0.2.0',
-                                     arch = 'x86_64',
-                                     os = 'linux',
-                                     interface_port     = '8888',
-                                     interface_protocol = 'http',
+                                     image_name = 'sarusso/jupyternotebook',
+                                     image_tag  = 'v0.2.0',
+                                     image_arch = 'amd64',
+                                     image_os   = 'linux',
+                                     interface_port      = '8888',
+                                     interface_protocol  = 'http',
                                      interface_transport = 'tcp/ip',
                                      supports_custom_interface_port = True,
                                      supports_interface_auth = True,
                                      interface_auth_user = None)
 
+            # Official Jupyter containers
+            for tag in ['lab-3.2.2', 'lab-3.1.17']:
+                
+                Container.objects.create(user     = None,
+                                         name     = 'Jupyter Data Science Lab',
+                                         description = 'The official Jupyter Lab. The Data Science variant, which includes libraries for data analysis from the Julia, Python, and R communities.',
+                                         registry = 'docker.io',
+                                         image_name = 'jupyter/scipy-notebook',
+                                         image_tag  = tag,
+                                         image_arch = None,
+                                         image_os   = None,
+                                         interface_port      = '8888',
+                                         interface_protocol  = 'http',
+                                         interface_transport = 'tcp/ip',
+                                         supports_custom_interface_port = True,
+                                         supports_interface_auth = True)
+                
+                for arch in ['amd64', 'arm64']:
+                    Container.objects.create(user     = None,
+                                             name     = 'Jupyter Lab',
+                                             description = 'The official Jupyter Lab. The Scipy variant, which includes popular packages from the scientific Python ecosystem.',
+                                             registry = 'docker.io',
+                                             image_name = 'jupyter/scipy-notebook',
+                                             image_tag  = tag,
+                                             image_arch = arch,
+                                             image_os   = 'linux',
+                                             interface_port      = '8888',
+                                             interface_protocol  = 'http',
+                                             interface_transport = 'tcp/ip',
+                                             supports_custom_interface_port = True,
+                                             supports_interface_auth = True)
+
+
             # SSH server
             Container.objects.create(user     = None,
                                      name     = 'SSH server',
                                      description = 'An SSH server supporting X forwarding as well.',
                                      registry = 'docker.io',
-                                     image    = 'sarusso/ssh',
-                                     tag      = 'v0.2.0',
-                                     arch = 'x86_64',
-                                     os = 'linux',
+                                     image_name = 'sarusso/ssh',
+                                     image_tag  = 'v0.2.0',
+                                     image_arch = 'amd64',
+                                     image_os   = 'linux',
                                      interface_port     = '22',
                                      interface_protocol = 'ssh',
                                      interface_transport = 'tcp/ip',
@@ -232,7 +265,7 @@ to provide help, news and informations on your deployment. Or you can just ignor
                                      access_mode = 'internal',
                                      auth_mode = 'internal',
                                      wms = None,
-                                     container_runtimes = 'docker')
+                                     container_runtimes = ['docker'])
 
             
             # Demo standalone computing plus conf
@@ -243,7 +276,7 @@ to provide help, news and informations on your deployment. Or you can just ignor
                                                                  auth_mode = 'user_keys',
                                                                  wms = None,
                                                                  conf = {'host': 'slurmclusterworker-one'},
-                                                                 container_runtimes = 'singularity')
+                                                                 container_runtimes = ['singularity'])
     
             # Add testuser extra conf for this computing resource
             testuser.profile.add_extra_conf(conf_type = 'computing_user', object=demo_singlenode_computing, value= 'slurmtestuser')
@@ -256,7 +289,7 @@ to provide help, news and informations on your deployment. Or you can just ignor
                                                             auth_mode = 'user_keys',
                                                             wms = 'slurm',
                                                             conf = {'host': 'slurmclustermaster-main', 'default_partition': 'partition1'},
-                                                            container_runtimes = 'singularity')
+                                                            container_runtimes = ['singularity'])
            
             # Add testuser extra conf for this computing resource
             testuser.profile.add_extra_conf(conf_type = 'computing_user', object=demo_slurm_computing, value= 'slurmtestuser')
diff --git a/services/webapp/code/rosetta/core_app/migrations/0022_auto_20211121_1341.py b/services/webapp/code/rosetta/core_app/migrations/0022_auto_20211121_1341.py
new file mode 100644
index 0000000000000000000000000000000000000000..a7de65727fd20083d6f0ae1f9121684a512a81cd
--- /dev/null
+++ b/services/webapp/code/rosetta/core_app/migrations/0022_auto_20211121_1341.py
@@ -0,0 +1,18 @@
+# Generated by Django 2.2.1 on 2021-11-21 13:41
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('core_app', '0021_container_interface_auth_user'),
+    ]
+
+    operations = [
+        migrations.RenameField(
+            model_name='computing',
+            old_name='container_runtimes',
+            new_name='container_runtime',
+        ),
+    ]
diff --git a/services/webapp/code/rosetta/core_app/migrations/0023_auto_20211121_1342.py b/services/webapp/code/rosetta/core_app/migrations/0023_auto_20211121_1342.py
new file mode 100644
index 0000000000000000000000000000000000000000..dcde2e0c7b6059129e10bed3cd7d9c7de556481a
--- /dev/null
+++ b/services/webapp/code/rosetta/core_app/migrations/0023_auto_20211121_1342.py
@@ -0,0 +1,24 @@
+# Generated by Django 2.2.1 on 2021-11-21 13:42
+
+import django.contrib.postgres.fields.jsonb
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('core_app', '0022_auto_20211121_1341'),
+    ]
+
+    operations = [
+        migrations.RemoveField(
+            model_name='computing',
+            name='container_runtime',
+        ),
+        migrations.AddField(
+            model_name='computing',
+            name='container_runtimes',
+            field=django.contrib.postgres.fields.jsonb.JSONField(default=['docker'], verbose_name='Container runtimes'),
+            preserve_default=False,
+        ),
+    ]
diff --git a/services/webapp/code/rosetta/core_app/migrations/0024_computing_emulated_archs.py b/services/webapp/code/rosetta/core_app/migrations/0024_computing_emulated_archs.py
new file mode 100644
index 0000000000000000000000000000000000000000..0add854a817e3e9de8d0bec98ffb379c5cd4af18
--- /dev/null
+++ b/services/webapp/code/rosetta/core_app/migrations/0024_computing_emulated_archs.py
@@ -0,0 +1,19 @@
+# Generated by Django 2.2.1 on 2021-11-21 13:42
+
+import django.contrib.postgres.fields.jsonb
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('core_app', '0023_auto_20211121_1342'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='computing',
+            name='emulated_archs',
+            field=django.contrib.postgres.fields.jsonb.JSONField(blank=True, null=True, verbose_name='Emulated architectures'),
+        ),
+    ]
diff --git a/services/webapp/code/rosetta/core_app/migrations/0025_auto_20211122_1332.py b/services/webapp/code/rosetta/core_app/migrations/0025_auto_20211122_1332.py
new file mode 100644
index 0000000000000000000000000000000000000000..4be61771093dc932cb2d367e45736f604c04f3d9
--- /dev/null
+++ b/services/webapp/code/rosetta/core_app/migrations/0025_auto_20211122_1332.py
@@ -0,0 +1,38 @@
+# Generated by Django 2.2.1 on 2021-11-22 13:32
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('core_app', '0024_computing_emulated_archs'),
+    ]
+
+    operations = [
+        migrations.RenameField(
+            model_name='container',
+            old_name='arch',
+            new_name='image_arch',
+        ),
+        migrations.RenameField(
+            model_name='container',
+            old_name='image',
+            new_name='image_name',
+        ),
+        migrations.RenameField(
+            model_name='container',
+            old_name='os',
+            new_name='image_os',
+        ),
+        migrations.RenameField(
+            model_name='container',
+            old_name='tag',
+            new_name='image_tag',
+        ),
+        migrations.AddField(
+            model_name='container',
+            name='image_digest',
+            field=models.CharField(blank=True, max_length=96, null=True, verbose_name='SHA 256 digest'),
+        ),
+    ]
diff --git a/services/webapp/code/rosetta/core_app/migrations/0026_auto_20211123_0037.py b/services/webapp/code/rosetta/core_app/migrations/0026_auto_20211123_0037.py
new file mode 100644
index 0000000000000000000000000000000000000000..2e335e86ceaf3ab1ca80d72d76e635e1dd794e43
--- /dev/null
+++ b/services/webapp/code/rosetta/core_app/migrations/0026_auto_20211123_0037.py
@@ -0,0 +1,23 @@
+# Generated by Django 2.2.1 on 2021-11-23 00:37
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('core_app', '0025_auto_20211122_1332'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='container',
+            name='image_arch',
+            field=models.CharField(blank=True, max_length=36, null=True, verbose_name='Architecture'),
+        ),
+        migrations.AlterField(
+            model_name='container',
+            name='image_os',
+            field=models.CharField(blank=True, max_length=36, null=True, verbose_name='Operating system'),
+        ),
+    ]
diff --git a/services/webapp/code/rosetta/core_app/migrations/0027_computing_supported_archs.py b/services/webapp/code/rosetta/core_app/migrations/0027_computing_supported_archs.py
new file mode 100644
index 0000000000000000000000000000000000000000..cb6ee53a3d36f7ea3e8270d5c013d2e7d120bbb2
--- /dev/null
+++ b/services/webapp/code/rosetta/core_app/migrations/0027_computing_supported_archs.py
@@ -0,0 +1,19 @@
+# Generated by Django 2.2.1 on 2021-11-24 00:25
+
+import django.contrib.postgres.fields.jsonb
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('core_app', '0026_auto_20211123_0037'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='computing',
+            name='supported_archs',
+            field=django.contrib.postgres.fields.jsonb.JSONField(blank=True, null=True, verbose_name='Supported architectures'),
+        ),
+    ]
diff --git a/services/webapp/code/rosetta/core_app/migrations/0028_computing_arch.py b/services/webapp/code/rosetta/core_app/migrations/0028_computing_arch.py
new file mode 100644
index 0000000000000000000000000000000000000000..7088e4c1b66f07a73e70a25514cf992ed8f865c8
--- /dev/null
+++ b/services/webapp/code/rosetta/core_app/migrations/0028_computing_arch.py
@@ -0,0 +1,19 @@
+# Generated by Django 2.2.1 on 2021-11-24 01:00
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('core_app', '0027_computing_supported_archs'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='computing',
+            name='arch',
+            field=models.CharField(default='amd64', max_length=255, verbose_name='Architecture'),
+            preserve_default=False,
+        ),
+    ]
diff --git a/services/webapp/code/rosetta/core_app/models.py b/services/webapp/code/rosetta/core_app/models.py
index 77514a195336d0f778c95a0318ea50c6e6f4c07b..e772eea43853f599a29c23658e436312d2a2fcb6 100644
--- a/services/webapp/code/rosetta/core_app/models.py
+++ b/services/webapp/code/rosetta/core_app/models.py
@@ -1,5 +1,6 @@
 import uuid
 import json
+import base64
 from django.conf import settings
 from django.db import models
 from django.contrib.auth.models import User, Group
@@ -110,19 +111,22 @@ class Container(models.Model):
     group = models.ForeignKey(Group, related_name='containers', on_delete=models.CASCADE, blank=True, null=True)
     # If a container has no group, it will be available to anyone. Can be created, edited and deleted only by admins.
 
-
     # Generic attributes
     name        = models.CharField('Name', max_length=255, blank=False, null=False)
     description = models.TextField('Description', blank=True, null=True)
     
-    # Registry-related attributes
+    # Registry
     registry = models.CharField('Registry', max_length=255, blank=False, null=False)
-    image    = models.CharField('Image', max_length=255, blank=False, null=False)
-    tag      = models.CharField('Tag', max_length=255, blank=False, null=False, default='latest')
 
-    # Platform-related
-    arch = models.CharField('Architecture', max_length=36, blank=False, null=False, default='x86_64')
-    os   = models.CharField('Operating system', max_length=36, blank=False, null=False, default='linux')
+    # Image name
+    image_name = models.CharField('Image', max_length=255, blank=False, null=False)
+    
+    # Image identifiers
+    image_tag  = models.CharField('Tag', max_length=255, blank=False, null=False, default='latest')
+    image_arch = models.CharField('Architecture', max_length=36, blank=True, null=True)
+    image_os   = models.CharField('Operating system', max_length=36, blank=True, null=True)
+    # -- OR --
+    image_digest  = models.CharField('SHA 256 digest', max_length=96, blank=True, null=True)
     
     # TODO: do we want more control with respect to kernel, CPUs, instruction sets? 
     # requires = i.e. kernel > 3, intel, AVX2
@@ -142,16 +146,30 @@ class Container(models.Model):
 
     def __str__(self):
         user_str = self.user.email if self.user else None
-        return str('Container "{}" of user "{}" with image "{}" and tag "{}" on registry "{}" '.format(self.name, user_str, self.image, self.tag, self.registry))
+        return str('Container "{}" of user "{}" with image name "{}" and image tag "{}" on registry "{}" '.format(self.name, user_str, self.image_name, self.image_tag, self.registry))
 
+    def save(self, *args, **kwargs):
+        # Check that digest starts with sha256:
+        if self.image_digest and not self.image_digest.startswith('sha256:'):
+            raise ValueError('The digest field must start with "sha256:"')
+        
+        super(Container, self).save(*args, **kwargs)
 
-    @ property
+    @property
+    def family_id(self):
+        id_as_str = '{}\t{}\t{}'.format(self.name, self.registry, self.image_name)
+        id_as_base64_str = base64.b64encode(id_as_str.encode('utf8')).decode('utf8')
+        return id_as_base64_str
+
+    @property
     def color(self):
-        string_int_hash = hash_string_to_int(self.image + self.tag + self.registry)
+        string_int_hash = hash_string_to_int(self.name + self.registry + self.image_name)
         color_map_index = string_int_hash % len(color_map)
         return color_map[color_map_index]
 
 
+
+
 #=========================
 #  Computing resources
 #=========================
@@ -165,16 +183,24 @@ class Computing(models.Model):
     name        = models.CharField('Name', max_length=255, blank=False, null=False)
     description = models.TextField('Description', blank=True, null=True)
 
-    # Tye (standalone / cluster)
+    # Type (standalone / cluster) and arch (i.e. amd64)
     type = models.CharField('Type', max_length=255, blank=False, null=False)
+    arch = models.CharField('Architecture', max_length=255, blank=False, null=False)
 
     # Interfce and interaction definition
     access_mode = models.CharField('Access (control) mode', max_length=36, blank=False, null=False)
     auth_mode   = models.CharField('Auth mode', max_length=36, blank=False, null=False)
     wms         = models.CharField('Workload management system', max_length=36, blank=True, null=True)
     
-    # Supported container runtimes
-    container_runtimes = models.CharField('Container runtimes', max_length=256, blank=False, null=False) 
+    # Supported container runtimes ['docker', 'singularity']
+    container_runtimes = JSONField('Container runtimes', blank=False, null=False)
+    #container_runtime = models.CharField('Container runtimes', max_length=256, blank=False, null=False)
+ 
+    # Supported architectures (i.e. 386 for amd64), as list: ['386']
+    supported_archs = JSONField('Supported architectures', blank=True, null=True) 
+
+    # Emulated architectures, by container runtime: {'docker': ['arm64/v7', 'arm64/v8']    
+    emulated_archs = JSONField('Emulated architectures', blank=True, null=True) 
 
     # Conf
     conf = JSONField(blank=True, null=True)
@@ -203,7 +229,7 @@ class Computing(models.Model):
     @property
     def default_container_runtime(self):
         return str(self.container_runtimes).split(',')[0]
-
+    
 
     #=======================
     # Computing manager
diff --git a/services/webapp/code/rosetta/core_app/templates/add_software.html b/services/webapp/code/rosetta/core_app/templates/add_software.html
index 668480db5ab5e5ec987492fe8ca9f9a5496bea49..9487623e74a2b1b1f77e143603e2000732c25770 100644
--- a/services/webapp/code/rosetta/core_app/templates/add_software.html
+++ b/services/webapp/code/rosetta/core_app/templates/add_software.html
@@ -44,16 +44,16 @@
            </tr>
 
            <tr>
-            <td><b>Image</b></td>
+            <td><b>Image&nbsp;name</b></td>
             <td>
-             <input type="text" name="container_image" value="" placeholder="" size="23" required />
+             <input type="text" name="container_image_name" value="" placeholder="" size="23" required />
             </td>
            </tr>
 
            <tr>
-            <td><b>Tag</b></td>
+            <td><b>Image tag</b></td>
             <td>
-             <input type="text" name="container_tag" value="latest" size="23" required />
+             <input type="text" name="container_image_tag" value="latest" size="23" required />
             </td>
            </tr>
 
@@ -77,7 +77,7 @@
              {% else %}
              <select name="container_interface_protocol" >
              <option value="http" selected>http</option>
-             <option value="https" selected>https</option>
+             <option value="https">https</option>
              </select>
              {% endif %}
             </td>
@@ -94,21 +94,25 @@
            <table class="dashboard" style="width:360px; margin-bottom:25px">
 
            <tr>
-            <td><b>Architecture</b></td><td>
-              <select name="container_arch" >
-              <option value="x86_64" selected>x86_64</option>
-              </select>
+            <td><b>Image arch</b></td><td>
+              <input type="text" name="container_image_arch" value="" placeholder="" size="5" />
             </td>
            </tr>
 
            <tr>
-            <td><b>Operating System</b></td><td>
-              <select name="container_os" >
+            <td><b>Image OS</b></td><td>
+              <select name="container_image_os" >
               <option value="linux" selected>linux</option>
               </select>
             </td>
            </tr>
 
+           <tr>
+            <td><b>Image digest</b></td><td>
+              <input type="text" name="container_image_digest" value="" placeholder="sha256:..." size="15" />
+            </td>
+           </tr>
+
            <tr>
             <td><b>Interface transport</b></td><td>
               <select name="container_interface_transport" >
@@ -154,7 +158,7 @@
           
  
       {% else %}
-        Ok, Container added. Go back to your <a href="/containers">container list</a>.
+        Ok, software container added. Go back to <a href="/software">software</a>.
         
 
       {% endif %} 
diff --git a/services/webapp/code/rosetta/core_app/templates/components/computing.html b/services/webapp/code/rosetta/core_app/templates/components/computing.html
index dfbbb418239939e88ea9fffd955dc5d78952ace3..0ad13b5d71d7090ba89a27cadec6fd23690986b1 100644
--- a/services/webapp/code/rosetta/core_app/templates/components/computing.html
+++ b/services/webapp/code/rosetta/core_app/templates/components/computing.html
@@ -23,7 +23,7 @@
         <td><b>Type</b></td>
         <td>{{ data.computing.type }}</td>
        </tr>
-
+       
        <tr>
         <td><b>Access mode</b></td>
         <td>{{ data.computing.access_mode }}</td>
@@ -39,11 +39,20 @@
         <td>{{ data.computing.wms }}</td>
        </tr>
 
+       <tr>
+        <td><b>Arch</b></td>
+        <td>{{ data.computing.arch }}</td>
+       </tr>
+
        <tr>
         <td><b>Container runtimes</b></td>
         <td>{{ data.computing.container_runtimes }}</td>
        </tr>
 
+       <tr>
+        <td><b>Emulated archs</b></td>
+        <td>{{ data.computing.emulated_archs }}</td>
+       </tr>
 
        <tr>
         <td><b>Storages</b></td>
@@ -85,11 +94,7 @@
         {% endif %}
         <div class="image-version-box">
         <b>Type:</b> {{ computing.type }}<br/>
-        <!--  -->{% if computing.auth_mode == 'user_keys' %}
-        <b>Access:</b> user keys
-        {% else %}
-        <b>Access:</b> open
-        {% endif %}
+        <b>Arch:</b> {{ computing.arch }}
         <br/>
         <b>Storages:</b>
         {% if not computing.storages.all %}
@@ -115,6 +120,7 @@
         {% csrf_token %}
         <input type="hidden" name="step" value="{{ data.next_step }}" />
         <input type="hidden" name="task_container_uuid" value="{{container.uuid}}">
+        <input type="hidden" name="task_container_arch" value="{{container_arch}}">
         <input type="hidden" name="task_computing_uuid" value="{{computing.uuid}}">
         <input type="submit" value="Choose" class="btn btn-connect">
         </form>
diff --git a/services/webapp/code/rosetta/core_app/templates/components/container.html b/services/webapp/code/rosetta/core_app/templates/components/container.html
index d6981795f90ab97aa5196f0db2974db50e4fbb17..49a60652d435e4763dde73d6ce08664012acb593 100644
--- a/services/webapp/code/rosetta/core_app/templates/components/container.html
+++ b/services/webapp/code/rosetta/core_app/templates/components/container.html
@@ -1,8 +1,13 @@
 
 
-      {% if details %}      
+      {% if details %}     
 
-      <table class="dashboard" style="margin:10px; max-width:600px">
+      <div style="width:400px; float:left; border: #e0e0e0 solid 1px; margin:10px; background:#f8f8f8; margin-bottom:15px">
+      <table class="dashboard" style="margin:0px; border:0px; width:398px">
+
+       <tr>
+        <td colspan=2 align=center style="padding:10px; font-size:1.2em"><a href="/software/?container_uuid={{ container.uuid }}">{{ container.name }} <font style="font-size:0.9em">({{ container.image_tag }})</font></a></td>
+       </tr>
         
        <tr>
         <td colspan="2" style="background:{{ container.color }}; height:15px"></td>
@@ -10,41 +15,36 @@
 
        <tr><td colspan=2 style="height:5px"></td></tr>
 
-
        <tr>
-        <td><b>Name</b></td>
-        <td>{{ container.name }}</td>
+        <td colspan=2>{{ container.description }}</td>
        </tr>
 
+       <tr><td colspan=2><hr style="margin:5px"></td></tr>
+
        <tr>
         <td><b>Owner</b></td>
         <td>{% if container.user %}{{ container.user }}{% else %}platform{% endif %}</td>
        </tr>
 
-       <tr>
-        <td><b>Description</b></td>
-        <td>{{ container.description }}</td>
-       </tr>
-
-       <tr><td colspan=2><hr style="margin:5px"></td></tr>
-
        <tr>
         <td><b>Registry</b></td>
         <td>{{ container.registry }}</td>
        </tr>
 
        <tr>
-        <td><b>Image</b></td>
-        <td><code>{{ container.image }}</code></td>
+        <td><b>Image&nbsp;name</b></td>
+        <td><code>{{ container.image_name }}</code></td>
        </tr>
 
        <tr>
-        <td><b>Tag</b></td>
-        <td>{{ container.tag }}</td>
+        <td><b>Image tag</b></td>
+        <td><span class="badge badge-secondary">{{ container.image_tag }}</span></td>
        </tr>
 
        <tr><td colspan=2><hr style="margin:5px"></td></tr>
-
+       </table>
+       
+      <table class="dashboard" style="margin:0px; border:0px;">
        <tr>
         <td><b>Interface protocol</b></td>
         <td>{{ container.interface_protocol }}</td>
@@ -61,13 +61,24 @@
        </tr>
 
        <tr>
-        <td><b>Architecture</b></td>
-        <td>{{ container.arch }}</td>
+        <td><b>Image arch</b></td>
+        <td>{{ container.image_arch }}</td>
        </tr>
 
        <tr>
-        <td><b>Operating System</b></td>
-        <td>{{ container.os }}</td>
+        <td><b>Image OS</b></td>
+        <td>{{ container.image_os }}</td>
+       </tr>
+
+       <tr>
+        <td><b>Image&nbsp;digest</b></td>
+        <td>
+        {% if container.image_digest %}
+        <input type="text" style="margin:0 "size=25 class="form-control" placeholder="" value="{{ container.image_digest }}" name='digest' readonly>
+        {% else %}
+        None
+        {% endif %}
+        </td>
        </tr>
 
        <tr><td colspan=2><hr style="margin:5px"></td></tr>
@@ -101,7 +112,7 @@
        </tr>
        {% endif %}
       </table>
-      <br/>
+      </div>
       
       
       {% else %}
@@ -109,7 +120,7 @@
 
         
         <div style="padding:10px; margin-top:5px; text-align:center; border-bottom: {{container.color}} solid 10px; ">
-        <a href="/software/?uuid={{ container.uuid }}">{{ container.name }}</a>&nbsp; 
+        <a href="/software/?container_uuid={{ container.uuid }}">{{ container.name }}</a>&nbsp; 
         </div>
         
         <div style="padding:10px; height: 110px; vertical-align: middle; ">
@@ -124,8 +135,13 @@
         
         <div class="image-version-box">
         <!-- <font style="font-family:monospace; font-size:1.2em"></font> -->
-        <b>Image:</b> <code>{{ container.image }}</code><br/>
-        <b>Tag:</b> &nbsp;{{ container.tag }}
+        <b>Image:</b> <code>{{ container.image_name }}</code><br/>
+        <b>Tag:</b> &nbsp;<span class="badge badge-secondary" style="margin-right:3px">{{ container.image_tag }}</span>
+        {% if container.image_arch %}
+        <font style="font-size:0.9em">({{ container.image_arch }})</font>
+        {% endif %}
+        
+        <!--  &nbsp; <b>Arch:</b> {{ container.image_arch }} -->
         </div> 
        
         </div>
diff --git a/services/webapp/code/rosetta/core_app/templates/components/container_family.html b/services/webapp/code/rosetta/core_app/templates/components/container_family.html
new file mode 100644
index 0000000000000000000000000000000000000000..f8e80181b9570a16421fea999758f88d83020dfb
--- /dev/null
+++ b/services/webapp/code/rosetta/core_app/templates/components/container_family.html
@@ -0,0 +1,115 @@
+
+      {% if data.details %}
+      {% for container in container_family.members %}
+      {% include "components/container.html" with container=container details=data.details %}
+      {% endfor %}
+      
+      {% else %}    
+
+      <div style="width:300px; float:left; border: #e0e0e0 solid 1px; margin:10px; background:#f8f8f8; margin-bottom:15px">
+        <form action="/new_task" method=GET>
+        <input type="hidden" name="step" value="two">
+        
+        
+        <div style="padding:10px; margin-top:5px; text-align:center; border-bottom: {{container_family.color}} solid 10px; ">
+        <a href="/software/?container_family_id={{ container_family_id }}&details=True">{{ container_family.name }}</a>&nbsp; 
+        </div>
+        
+        <div style="padding:10px; height: 125px; ">
+        <!-- <div style="position: relative; top: 50%; transform: translateY(-50%);"> -->
+        
+        {% if container_family.description %} 
+        <div class="description-box" title="{{ container_family.description }}">
+        {{ container_family.description }}
+        </div>
+        {% else %}
+        <br/>  
+        {% endif %}
+        
+        <div class="image-version-box">
+        <b>Image:</b> <code>{{ container_family.image_name }}</code><br/>
+        <div style="margin-top:2px">
+        
+        <!-- <span style="vertical-align:top;"><b>Tag:</b>&nbsp;</span>
+        <select name="task_container_uuid" style="font-size:0.8em">
+        {% for container in container_family.members %}
+        <option value="{{ container.uuid }}">{{ container.image_tag }} ({{ container.image_arch }})</option>
+        {% endfor %}
+        </select> -->
+
+        <!--<span style="vertical-align:top; margin-left:0px"><b>Tag:</b>&nbsp;</span>
+        <select name="task_container" style="font-size:0.8em">
+        {% for arch,container_by_tags in container_family.container_by_tags_by_arch.items %}
+        {% if not arch %}
+        {% for tag,container in container_by_tags.items %}
+        <option value="family:{{ container_family_id }},tag:{{ tag }}">{{ tag }}</option>
+        {% endfor %}
+        {% endif %}
+        {% endfor %}
+
+        {% for arch,container_by_tags in container_family.container_by_tags_by_arch.items %}
+        {% if arch %}
+        <optgroup label="{{ arch }}">
+        {% for tag,container in container_by_tags.items %}
+        <option value="uuid:{{ container.uuid }}">{{ tag }}</option>
+        {% endfor %}
+        {% endif %}
+        {% endfor %}
+        </optgroup>-->
+
+
+        <span style="vertical-align:top; margin-left:0px"><b>Tag:</b>&nbsp;</span>
+        <select name="task_container_uuid" style="font-size:0.8em">
+        {% for arch,container_by_tags in container_family.container_by_tags_by_arch.items %}
+        {% if not arch %}
+        {% for tag,container in container_by_tags.items %}
+        <option value="{{container.uuid}}">{{ tag }}</option>
+        {% endfor %}
+        {% endif %}
+        {% endfor %}
+
+        {% for arch,container_by_tags in container_family.container_by_tags_by_arch.items %}
+        {% if arch %}
+        <optgroup label="{{ arch }}">
+        {% for tag,container in container_by_tags.items %}
+        <option value="{{container.uuid}}">{{ tag }}</option>
+        {% endfor %}
+        {% endif %}
+        {% endfor %}
+        </optgroup>
+
+
+   
+
+        </select>
+
+            
+        </div>
+        </div>
+        <!-- </div> -->
+        </div>
+        
+        <div style="margin-bottom:8px; margin-top: 3px; text-align:center">
+        {% if not disable_play_button %}
+        
+               
+        <button type="submit" onclick="myFunction()" class="btn-link btn btn-light" style="border: #c0c0c0 1px solid">
+        &nbsp;<i class="fa fa-play" style="color:green"></i>
+        </button>
+        
+        {% endif %}
+        </form>
+        </div>    
+      
+      
+      
+      </div>
+      
+      {% endif %}
+
+
+
+
+
+
+      
\ No newline at end of file
diff --git a/services/webapp/code/rosetta/core_app/templates/components/container_family_mah.html b/services/webapp/code/rosetta/core_app/templates/components/container_family_mah.html
new file mode 100644
index 0000000000000000000000000000000000000000..c2bf49b5e147b9e98f2e04c0b2a6f4e544a76c49
--- /dev/null
+++ b/services/webapp/code/rosetta/core_app/templates/components/container_family_mah.html
@@ -0,0 +1,64 @@
+
+
+      <div style="width:300px; float:left; border: #e0e0e0 solid 1px; margin:10px; background:#f8f8f8; margin-bottom:15px">
+        <form action="/aaa" method=GET>
+        
+        
+        <div style="padding:10px; margin-top:5px; text-align:center; border-bottom: {{container.color}} solid 10px; ">
+        <a href="/software/?container_family={{ family_id }}">{{ container_family.name }}</a>&nbsp; 
+        </div>
+        
+        <div style="padding:10px; height: 125px; ">
+        <!-- <div style="position: relative; top: 50%; transform: translateY(-50%);"> -->
+        
+        {% if container_family.description %} 
+        <div class="description-box" title="{{ container_family.description }}">
+        {{ container_family.description }}
+        </div>
+        {% else %}
+        <br/>  
+        {% endif %}
+        
+        <div class="image-version-box">
+        <b>Image:</b> <code>{{ container_family.image }}</code><br/>
+        <div style="margin-top:2px">
+        
+        <span style="vertical-align:top;"><b>Tag:</b>&nbsp;</span>
+        <select name="task_container_uuid_and_arch" style="font-size:0.8em">
+        {% for arch,container_by_tags in container_family.container_by_tags_by_arch.items %}
+        <optgroup label={{ arch }}>
+        {% for tag,container in container_by_tags.items %}
+        <option value="{{ container.uuid }}-{{ arch }}">{{ tag }}</option>
+        {% endfor %}
+        </optgroup>
+        {% endfor %}
+        </select>
+             
+        </div>
+        </div>
+        <!-- </div> -->
+        </div>
+        
+        <div style="margin-bottom:8px; margin-top: 3px; text-align:center">
+        {% if not disable_play_button %}
+        
+               
+        <button type="submit" onclick="myFunction()" class="btn-link btn btn-light" style="border: #c0c0c0 1px solid">
+        &nbsp;<i class="fa fa-play" style="color:green"></i>
+        </button>
+        
+        {% endif %}
+        </form>
+        </div>    
+      
+      
+      
+      </div>
+      
+
+
+
+
+
+
+      
\ No newline at end of file
diff --git a/services/webapp/code/rosetta/core_app/templates/components/task.html b/services/webapp/code/rosetta/core_app/templates/components/task.html
index 35ef478837dccaf21412545169f924017b490827..effe0f1ccb5a21bf3e92b3ae3cc1456546993aa0 100644
--- a/services/webapp/code/rosetta/core_app/templates/components/task.html
+++ b/services/webapp/code/rosetta/core_app/templates/components/task.html
@@ -5,6 +5,8 @@
             <div style="margin-top:5px; padding:10px; text-align:center; border-bottom: #f8f8f8 solid 1px; ">
             Task <b>{{data.task.name}}</b> summary
             </div>
+            <hr style="margin:0">
+            
           {% else %}
           <div style="width:350px; float:left; border: #e0e0e0 solid 1px; margin:10px; background:#f8f8f8; margin-bottom:20px">
             
@@ -27,18 +29,18 @@
             </div> -->
 
             
-            <div style="padding:10px;">
+            <div style="padding:10px; padding-left:15px; padding-right:15px; text-align:left;">
             <!-- <b>Container:</b> {{ task.container.name }} <span style="font-size:14px; background-color:{{task.container.color}}">&nbsp;&nbsp;&nbsp;&nbsp;</span> <br/>
             <b>Computing:</b> {{ task.computing.name }} <span style="font-size:14px; background-color:{{task.computing.color}}">&nbsp;&nbsp;&nbsp;&nbsp;</span><br/> -->
 
-            <b>Software:</b>
-            <a href="/software/?uuid={{ task.container.uuid }}" style="color:{{task.container.color}}">{{ task.container.name }}</a>
+            <b>Software container:</b>
+            <a href="/software/?container_uuid={{ task.container.uuid }}" style="color:{{task.container.color}}">{{ task.container.name }}</a>
             {% if task.container.type == 'docker' %}<img src="/static/img/docker-logo.svg" style="height:18px; width:18px; margin-bottom:4px" />{% endif %}
             {% if task.container.type == 'singularity' %}<img src="/static/img/singularity-logo.svg" style="height:18px; width:18px; margin-bottom:4px" />{% endif %}
 
             <br/>
             
-            <b>Computing:</b> <a href="/computing/?uuid={{ task.computing.uuid }}">{{ task.computing.name }}</a>
+            <b>Computing resource:</b> <a href="/computing/?uuid={{ task.computing.uuid }}">{{ task.computing.name }}</a>
             <!-- <a href="/computing/?uuid={{ task.computing.uuid }}" no_style="color:{{task.computing.color}}"><i class="fa fa-external-link" ></i></a><br/> -->           
             
             <div style="margin-top:2px">
diff --git a/services/webapp/code/rosetta/core_app/templates/new_task.html b/services/webapp/code/rosetta/core_app/templates/new_task.html
index 23db343aefb01a77fe92c45076ade8a1de3436fc..807e554010b057c255154ef7cf15a7d243bf77fd 100644
--- a/services/webapp/code/rosetta/core_app/templates/new_task.html
+++ b/services/webapp/code/rosetta/core_app/templates/new_task.html
@@ -24,7 +24,7 @@
       <div style="float:left; background:#ffffff; margin-left:10px; margin-right:10px; margin-top:0px; margin-bottom:20px">
           <h4>Software container</h4>
           <div class="row" style="padding:5px">
-          {% include "components/container.html" with container=data.task_container disable_play_button=True %}
+          {% include "components/container.html" with container=data.task_container container_arch=data.task_container_arch disable_play_button=True  %}
           </div>
       </div>
       {% endif %}
@@ -36,7 +36,7 @@
           <h4>Computing resource</h4>
           <div class="row" style="padding:5px">
           {% for computing in data.computings %}
-          {% include "components/computing.html" with container=data.task_container %}
+          {% include "components/computing.html" with container=data.task_container container_arch=data.task_container_arch %}
           {% endfor %}
           </div>
       </div>
@@ -76,6 +76,7 @@
           <form action="/new_task/" method="POST">
           {% csrf_token %}
           <input type="hidden" name="task_container_uuid" value="{{data.task_container.uuid}}">
+          <input type="hidden" name="task_container_arch" value="{{data.task_container_arch}}">          
           <input type="hidden" name="step" value="{{ data.next_step }}" />
           <input type="hidden" name="task_name" value="{{ data.task_name }}" />
           <input type="hidden" name="task_container_uuid" value="{{ data.task_container.uuid }}" />
@@ -165,6 +166,18 @@
           <i class="fa fa-exclamation-triangle" style="color:orange"></i> This container does not support custom interface ports and the computing resource you selected might use a container runtime which does not support port mapping (Singularity). In this case, if the container interface port is already allocated, the task will fail to start.
           </p></div>
           {% endif %}
+
+          {% if data.arch_emulation %}
+          <div> <p style="font-size:15px; max-width:700px; margin-bottom:20px; margin-left:5px">
+          <i class="fa fa-exclamation-triangle" style="color:orange"></i> The selected software container architecture ({{ data.task_container_arch}}) can only be emulated on this computing resource, meaning the it will probably run quite slow.
+          </p></div>
+          {% endif %}
+
+          {% if data.arch_auto_selection %}
+          <div> <p style="font-size:15px; max-width:700px; margin-bottom:20px; margin-left:5px">
+          <i class="fa fa-exclamation-triangle" style="color:orange"></i> The selected software container does not specify any architecture. This will leave to the container runtime either to auto-select the right image architecture on the registry, or to fallback on emulation if not found. Beware of potential incompatibilities or slowdowns.
+          </p></div>
+          {% endif %}
           
           <!-- {% if data.task_container.interface_port and not data.task_container.supports_interface_auth %}
           <div> <p style="font-size:15px; max-width:700px; margin-bottom:20px; margin-left:5px">
diff --git a/services/webapp/code/rosetta/core_app/templates/software.html b/services/webapp/code/rosetta/core_app/templates/software.html
index 8be03d0b5deed876bd26394f2d26f618dc23ec76..4b9223bae72d2eac9a76c151044d202db3f0d182 100644
--- a/services/webapp/code/rosetta/core_app/templates/software.html
+++ b/services/webapp/code/rosetta/core_app/templates/software.html
@@ -9,8 +9,12 @@
   <div class="dashboard">
     <div class="span8 offset2">
       
-      {% if data.container %}
-      <h1><a href="/software">Software containers</a> <span style="font-size:18px"> / {{ data.container.name }}</span></h1>
+      {% if data.details or data.container %}
+      {% if data.container_families %}
+      <h1><a href="/software">Software containers</a> <span style="font-size:18px"> / {{ data.containers.0.name }}</span></h1>
+      {% else %}      
+      <h1><a href="/software">Software containers</a> <span style="font-size:18px"> / <a href="/software/?container_family_id={{data.container.family_id}}&details=True">{{ data.container.name }}</a> / {{ data.container.image_tag}}</span></h1>
+      {% endif %}
       {% else %}
       {% if data.mode == 'new_task' %}
       <h1>New Task</h1>
@@ -65,10 +69,16 @@
       <div class="row" style="padding:5px">
       {% if data.container %}
       {% include "components/container.html" with container=data.container details=True %}
-      {% else %} 
+      {% else %}     
+      {% if data.container_families %}
+      {% for container_family_id, container_family in data.container_families.items %}
+      {% include "components/container_family.html" with container_family=container_family container_family_id=container_family_id%}
+      {% endfor %}
+      {% else %}
       {% for container in data.containers %}
       {% include "components/container.html" with container=container %}
       {% endfor %}
+      {% endif  %}      
       {% endif %}
       </div>
       
diff --git a/services/webapp/code/rosetta/core_app/views.py b/services/webapp/code/rosetta/core_app/views.py
index 80f454208e16173b060ec5e5af49b827e1fca4ef..2e75f1ae5884da4fd367e0c1a4c3c58518b8c695 100644
--- a/services/webapp/code/rosetta/core_app/views.py
+++ b/services/webapp/code/rosetta/core_app/views.py
@@ -2,6 +2,7 @@ import os
 import uuid
 import json
 import subprocess
+import base64
 from django.conf import settings
 from django.shortcuts import render
 from django.contrib.auth import authenticate, login, logout
@@ -10,7 +11,7 @@ from django.contrib.auth.models import User
 from django.shortcuts import redirect
 from django.db.models import Q
 from .models import Profile, LoginToken, Task, TaskStatuses, Container, Computing, KeyPair, Page
-from .utils import send_email, format_exception, timezonize, os_shell, booleanize, debug_param, get_task_tunnel_host, get_task_proxy_host, random_username, setup_tunnel_and_proxy, finalize_user_creation
+from .utils import send_email, format_exception, timezonize, os_shell, booleanize, debug_param, get_task_tunnel_host, get_task_proxy_host, random_username, setup_tunnel_and_proxy, finalize_user_creation, get_md5
 from .decorators import public_view, private_view
 from .exceptions import ErrorMessage
 
@@ -496,7 +497,7 @@ def new_task(request):
         
     elif step == 'two':
         
-        # Get software container
+        # Get software container and arch
         data['task_container'] = get_task_container(request)
 
         # List all computing resources 
@@ -507,12 +508,34 @@ def new_task(request):
 
     elif step == 'three':
 
-        # Get software container
+        # Get software container and arch
         data['task_container'] = get_task_container(request)
 
         # Get computing resource
         data['task_computing'] = get_task_computing(request)
         
+        # Check that container required architecture is compatible with the computing resource
+        # TODO: support setting the container runtime when creating the task
+        # TODO: refactor and unroll this code
+        if data['task_container'].image_arch:
+            if (data['task_container'].image_arch != data['task_computing'].arch) and (data['task_container'].image_arch not in data['task_computing'].supported_archs):
+
+                if data['task_computing'].emulated_archs:
+                    container_runtime = data['task_computing'].container_runtimes[0]
+                    
+                    if container_runtime in data['task_computing'].emulated_archs and data['task_container'].image_arch in data['task_computing'].emulated_archs[container_runtime]:
+                        data['arch_emulation'] = True
+                        
+                    else:
+                        raise ErrorMessage('This computing resource does not support architecture \'{}\' nor as native or emulated'.format(data['task_container'].image_arch))
+                
+                else:
+                    raise ErrorMessage('This computing resource does not support architecture \'{}\' nor as native or emulated'.format(data['task_container'].image_arch))
+
+        else:
+            data['arch_auto_selection'] = True
+            #raise ErrorMessage('Auto selecting architectures is not supported yet')
+
         # Generate random auth token        
         data['task_auth_token'] = str(uuid.uuid4())
 
@@ -523,7 +546,7 @@ def new_task(request):
 
     elif step == 'last':
 
-        # Get software container
+        # Get software container and arch
         data['task_container'] = get_task_container(request)
 
         # Get computing resource
@@ -691,8 +714,11 @@ def software(request):
     data['profile'] = Profile.objects.get(user=request.user)
 
     # Get action if any
-    uuid   = request.GET.get('uuid', None)
+    container_uuid = request.GET.get('container_uuid', None)
+    container_family_id = request.GET.get('container_family_id', None)
     action = request.GET.get('action', None)
+    details = booleanize(request.GET.get('details', False))
+
 
     # Get filter/search if any
     search_text   = request.POST.get('search_text', '')
@@ -701,6 +727,7 @@ def software(request):
     # Set back to page data
     data['search_owner'] = search_owner
     data['search_text']  = search_text
+    data['details'] = details
 
     # Are we using this page as first step of a new task?
     data['mode'] = request.GET.get('mode', None)
@@ -708,14 +735,14 @@ def software(request):
         data['mode'] = request.POST.get('mode', None)
 
 
-    # Do we have to operate on a specific container?
-    if uuid:
+    # Do we have to operate on a specific container, or family of containers?
+    if container_uuid:
 
         try:
 
             # Get the container (raises if none available including no permission)
             try:
-                container = Container.objects.get(uuid=uuid)
+                container = Container.objects.get(uuid=container_uuid)
             except Container.DoesNotExist:
                 raise ErrorMessage('Container does not exists or no access rights')                
             if container.user and container.user != request.user:
@@ -735,26 +762,93 @@ def software(request):
             data['error'] = 'Error in getting the software container or performing the required action'
             logger.error('Error in getting container with uuid="{}" or performing the required action: "{}"'.format(uuid, e))
             return render(request, 'error.html', {'data': data})
-
-
-    # Get containers (fitered by search term, or all)
-    if search_text:
-        search_query=(Q(name__icontains=search_text) | Q(description__icontains=search_text) | Q(image__icontains=search_text))
-        user_containers = Container.objects.filter(search_query, user=request.user)
-        platform_containers = Container.objects.filter(search_query, user=None)
+    
     else:
-        user_containers = Container.objects.filter(user=request.user)
-        platform_containers = Container.objects.filter(user=None)
+        # Ddo we have to operate on a container family?
+        if container_family_id:
+            
+            # Get back name, registry and image from contsainer url
+            container_name, container_registry, container_image_name = base64.b64decode(container_family_id.encode('utf8')).decode('utf8').split('\t')
+          
+            # get containers from the DB
+            user_containers = Container.objects.filter(user=request.user, name=container_name, registry=container_registry, image_name=container_image_name)
+            platform_containers = Container.objects.filter(user=None, name=container_name, registry=container_registry, image_name=container_image_name)
+        
+        else:    
+            
+            # Get containers (fitered by search term, or all)
+            if search_text:
+                search_query=(Q(name__icontains=search_text) | Q(description__icontains=search_text) | Q(image_name__icontains=search_text))
+                user_containers = Container.objects.filter(search_query, user=request.user)
+                platform_containers = Container.objects.filter(search_query, user=None)
+            else:
+                user_containers = Container.objects.filter(user=request.user)
+                platform_containers = Container.objects.filter(user=None)
     
-    # Filter by owner
-    if search_owner != 'All':
-        if search_owner == 'User':
-            platform_containers =[]
-        if search_owner == 'Platform':
-            user_containers = []
-
-    data['containers'] = list(user_containers) + list(platform_containers)
-
+            
+        # Ok, nilter by owner
+        if search_owner != 'All':
+            if search_owner == 'User':
+                platform_containers =[]
+            if search_owner == 'Platform':
+                user_containers = []
+                
+        # Create all container list
+        data['containers'] = list(user_containers) + list(platform_containers)
+            
+        # Merge containers with the same name, registry and image name
+        data['container_families'] = {}
+        
+        # Container family support class
+        class ContainerFamily(object):
+        
+            def __init__(self, id, name, registry, image_name):
+                self.id = id
+                self.name = name
+                self.registry = registry
+                self.image_name = image_name
+                self.description = None
+                self.members = []
+                self.all_archs = []
+                self.container_by_tags_by_arch = {} 
+    
+            def add(self, container):
+                self.members.append(container)
+    
+                if not self.description:
+                    self.description = container.description
+    
+                if not container.image_arch in self.all_archs:
+                    self.all_archs.append(container.image_arch)
+    
+                if not container.image_arch in self.container_by_tags_by_arch:
+                    self.container_by_tags_by_arch[container.image_arch]={}
+                self.container_by_tags_by_arch[container.image_arch][container.image_tag] = container
+                
+                # Lastly, add the container to the "all tags"
+                #if None not in self.container_by_tags_by_arch:
+                #    self.container_by_tags_by_arch[None]={}
+                #self.container_by_tags_by_arch[None][container.image_tag] = container
+    
+            
+            @ property
+            def color(self):
+                try:
+                    return self.members[0].color
+                except IndexError:
+                    return '#000000'
+            
+        # Populate container families
+        for container in data['containers']:
+            if container.family_id not in data['container_families']:
+                data['container_families'][container.family_id] = ContainerFamily(container.family_id, container.name, container.registry, container.image_name)
+            data['container_families'][container.family_id].add(container)
+        # Finalize the families
+        #for container.family_id in data['container_families']:
+        #    if len(data['container_families'][container.family_id].all_archs) == 1:
+        #        if data['container_families'][container.family_id].all_archs[0] != None:
+        #            data['container_families'][container.family_id].container_by_tags_by_arch.pop(None)
+                
     return render(request, 'software.html', {'data': data})
 
 
@@ -781,17 +875,20 @@ def add_software(request):
         # Container registry
         container_registry = request.POST.get('container_registry', None)
 
-        # Container image
-        container_image = request.POST.get('container_image',None)
+        # Container image name
+        container_image_name = request.POST.get('container_image_name',None)
         
-        # Container tag
-        container_tag = request.POST.get('container_tag', None)
+        # Container image tag
+        container_image_tag = request.POST.get('container_image_tag', None)
+
+        # Container image architecture
+        container_image_arch = request.POST.get('container_image_arch', None)
 
-        # Container architecture
-        container_arch = request.POST.get('container_arch')
+        # Container image OS 
+        container_image_os = request.POST.get('container_image_os', None)
 
-        # Container operating system
-        container_os = request.POST.get('container_os')
+        # Container image digest
+        container_image_digest = request.POST.get('container_image_digest', None)
 
         # Container interface port
         container_interface_port = request.POST.get('container_interface_port', None) 
@@ -829,14 +926,15 @@ def add_software(request):
         #logger.debug('Creating new container object with image="{}", type="{}", registry="{}", ports="{}"'.format(container_image, container_type, container_registry, container_ports))
 
         # Create
-        Container.objects.create(user        = request.user,
-                                 name        = container_name,
-                                 description = container_description,
-                                 registry    = container_registry,
-                                 image       = container_image,
-                                 tag         = container_tag,
-                                 arch        = container_arch,
-                                 os          = container_os,
+        Container.objects.create(user         = request.user,
+                                 name         = container_name,
+                                 description  = container_description,
+                                 registry     = container_registry,
+                                 image_name   = container_image_name,
+                                 image_tag    = container_image_tag,
+                                 image_arch   = container_image_arch,
+                                 image_os     = container_image_os,
+                                 image_digest = container_image_digest,
                                  interface_port      = container_interface_port,
                                  interface_protocol  = container_interface_protocol,
                                  interface_transport = container_interface_transport,